我正在尝试在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”。 所以我的问题是:我应该如何构建嵌套调用以获得我想要的结果 并获取已插入的对象的信息?
答案 0 :(得分: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)
}
}
}
可能存在一些语法错误,但这个想法就在那里。
答案 1 :(得分:2)
我不是ReactiveMongo中的mongoDB专家,但您似乎正在尝试使用NoSQL数据库,就像使用标准SQL数据库一样。请注意,mongoDB是异步的,这意味着操作可能会在将来执行,这就是插入/更新操作不会返回受影响的文档的原因。关于你的问题:
1如果对象不存在则插入它们并获取已插入的对象的信息?
您应该查看mongoDB db.collection.update()方法,并将upsert
参数调用为true。如果您负担得起,如果文档已存在于数据库中,则会更新文档,否则将插入文档。同样,此操作不会返回受影响的文档,但您可以通过访问last error来检查受影响的文档数量。请参阅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
这真的很有用! ;)