【问题标题】:Nested queries with ReactiveMongo使用 ReactiveMongo 的嵌套查询
【发布时间】:2015-04-27 15:17:25
【问题描述】:

我有一个文章集合,其中“标题”和“出版物”字段具有唯一的组合键约束。

当调用 insertOrUpdateArticle(a: Article) 时,它会首先尝试插入它,以防遇到约束,它应该更新文章 - 如果需要。

但是,在那之前我被困住了。当前错误是:

Error:(88, 57) type mismatch;
 found   : scala.concurrent.Future[scala.concurrent.Future[Boolean]]
 required: Boolean
            col_article.find(selector).one[Article].map {

来源:

def insertOrUpdateArticle(a: Article): Future[Boolean] = {
  // try insert article
  col_article.insert[Article](a).map {
    // article inserted
    lastError => {
      println("Article added.")
      true
    }
  }.recover {
    case lastError: LastError =>
      // check if article existed
      lastError.code.get match {
        case 11000 => {
          // article existed (duplicate key error)

          // load old article
          val selector = BSONDocument(
            "title" -> BSONString(a.title),
            "publication" -> BSONString(a.publication)
          )

          col_article.find(selector).one[Article].map {
            case Some(old_a: Article) => {
              // TODO: compare a with old_a
              // TODO: if a differs from old_a, update
              Future(true)
            }
            case None => {
              // something went wrong
              Future(false)
            }
          }
        }
        case _ => {
          println("DB.insertOrUpdateArticle() unexpected error code when inserting: " + lastError.code.get)
          false
        }
      }
    case ex =>
      println("DB.insertOrUpdateArticle() unexpected exception when inserting: " + ex)
      false
  }
}

我不确定在这里做什么。如果文章已保存或更新,代码应返回 Future(true),否则返回 false。我在这里错过了有关响应式mongo 和/或 scala 期货的一些东西。

【问题讨论】:

  • 据我所知.map.insert 的结果,这是一个Future[LastError] 与来自.find.one 的结果,它本身就是一个Future ,所以它最终提出了Future[Future[T]]。如果你想链接异步结果(又名Future[T]),你应该使用.flatMap(例如futureA.flatMap(res1 => futureB))或用于理解(例如for { res1 <- futureA; res2 <- futureB } yield ???})。
  • 我担心 flatMap 会出现与 map 相同的错误。我需要对恢复做出反应,不确定如何通过理解来解决。
  • 注意区别 b/w recover&recoverWith。没有特定于 RM,而是 Future 组合。
  • @cchantep super,在 Scala 文档中访问了 Future 页面,结果成功了,当然需要使用 recoverWith 创建一个新的未来,结果成功了。

标签: mongodb scala reactivemongo


【解决方案1】:

使用recoverWith创建新的Future是解决办法,修改代码:

def insertOrUpdateArticleOld(a: Article): Future[Boolean] = {
  // try insert article
  col_article.insert[Article](a).map {
    // article inserted
    lastError => {
      println("Article added.")
      true
    }
  }.recoverWith {
    case lastError: LastError =>
      // check if article existed
      lastError.code.get match {
        case 11000 => {
          // article existed (duplicate key error)

          // load old article
          val selector = BSONDocument(
            "title" -> BSONString(a.title),
            "publication" -> BSONString(a.publication)
          )

          col_article.find(selector).one[Article].flatMap {
            case Some(old_a: Article) => {
              // TODO: compare a with old_a
              // TODO: if a differs from old_a, update
              Future(true)
            }
            case None => {
              // something went wrong
              Future(false)
            }
          }
        }
        case _ => {
          println("DB.insertOrUpdateArticle() unexpected error code when inserting: " + lastError.code.get)
          Future(false)
        }
      }
    case ex =>
      println("DB.insertOrUpdateArticle() unexpected exception when inserting: " + ex)
      Future(false)
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-27
    • 2012-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-14
    相关资源
    最近更新 更多