0

我正在尝试在我的 play2 应用程序中将一些嵌套调用与 reactivemongo 结合起来。我得到一个从createObjects. 然后我遍历它们,检查对象是否存在于集合中,如果不存在则插入它们:

def dostuff() = Action {
    implicit request =>
      form.bindFromRequest.fold(
        errors => BadRequest(views.html.invite(errors)),
        form => {
        val objectsReadyForSave = createObjects(form.companyId, form.companyName, sms_pattern.findAllIn(form.phoneNumbers).toSet)
          Async {
            for(object <- objectsReadyForSave) {
                collection.find(BSONDocument("cId" -> object.get.cId,"userId" ->
                object.userId.get)).cursor.headOption.map { maybeFound =>
                maybeFound.map { found =>
                  Logger.info("Found record, do not insert")
                } getOrElse {
                  collection.insert(object)
                }
              }
            }
            Future(Ok(views.html.invite(form)))
          }            
          })
   }

我觉得这种方式不如它可以,感觉不是“play2”和“reactivemongo”。所以我的问题是:我应该如何构建我的嵌套调用以获得我想要的结果并获取已插入哪些对象的信息?

4

2 回答 2

2

这是我重写它的方法。

def dostuff() = Action { implicit request =>
  form.bindFromRequest.fold(
    errors => BadRequest(views.html.invite(errors)),
    form   => {
      createObjects(form.companyId,
        form.companyName,
        sms_pattern.findAllIn(form.phoneNumbers).toSet).map(ƒ)

      Ok(views.html.invite(form))
    }
  )
}

// ...
// In the model
// ...

def ƒ(cId: Option[String], userId: Option[String], logger: Logger) = {
  // You need to handle the case where obj.cId or obj.userId are None
  collection.find(BSONDocument("cId" -> obj.cId.get, "userId" -> obj.userId.get))
    .cursor
    .headOption
    .map { maybeFound =>
      maybeFound map { _ =>
        logger.info("Record found, do not insert")
      } getOrElse {
        collection.insert(obj)
      }
    }
}

可能有一些语法错误,但想法就在那里。

于 2013-05-22T13:40:11.230 回答
2

我不是 mongoDB 的专家,也不是 ReactiveMongo 的专家,但您似乎正在尝试以与使用标准 SQL 数据库相同的方式使用 NoSQL 数据库。请注意,mongoDB 是异步的,这意味着操作可能会在将来执行,这就是插入/更新操作不返回受影响文档的原因。关于你的问题:

1 插入不存在的对象并获取已插入的对象的信息?

您可能应该查看 mongoDB db.collection.update()方法并使用upsert参数为 true 调用它。如果您负担得起,这将更新已存在于数据库中的文档,否则将插入它们。同样,此操作不会返回受影响的文档,但您可以通过访问最后一个错误来检查有多少文档受到影响。请参阅reactivemongo.api.collections.GenericCollection#update,它返回一个Future[LastError].

2 对于所有插入的对象,将它们添加到列表中,然后使用 Ok() 调用将其返回。

再一次,插入/更新的文档将不会被退回。如果您确实需要返回完整的受影响文档,则需要进行另一个查询以检索匹配的文档。

我可能会以这种方式重写您的代码(没有错误/故障处理):

def dostuff() = Action {
    implicit request =>
        form.bindFromRequest.fold(
            errors => BadRequest(views.html.invite(errors)),
            form => {
                val objectsReadyForSave = createObjects(form.companyId, form.companyName, sms_pattern.findAllIn(form.phoneNumbers).toSet)
                Async {
                    val operations = for {
                        data <- objectsReadyForSave
                    } yield collection.update(BSONDocument("cId" -> data.cId.get, "userId" -> data.userId.get), data, upsert = true)

                    Future.sequence(operations).map {
                        lastErrors =>
                            Ok("Documents probably inserted/updated!")
                    }
                }
            }
        )
}

另请参阅 Scala 期货:http ://docs.scala-lang.org/overviews/core/futures.html

这真的很有用!;)

于 2013-05-28T16:03:18.703 回答