Mongodb 如何使用'$在';超过'_id';在mongo和play中
我用Mongodb 如何使用'$在';超过'_id';在mongo和play中,mongodb,scala,playframework,playframework-2.2,reactivemongo,Mongodb,Scala,Playframework,Playframework 2.2,Reactivemongo,我用playframework2.2.0和play2 reactivemongo 0.10.0-SNAPSHOT设置了一个项目。我想通过ID查询一些文档,方式类似于: def usersCollection = db.collection[JSONCollection]("users") val ids: List[String] = /* fetched from somewhere else */ val query = ?? val users = usersCollection.find
playframework2.2.0
和play2 reactivemongo 0.10.0-SNAPSHOT
设置了一个项目。我想通过ID查询一些文档,方式类似于:
def usersCollection = db.collection[JSONCollection]("users")
val ids: List[String] = /* fetched from somewhere else */
val query = ??
val users = usersCollection.find(query).cursor[User].collect[List]()
作为一个问题,我尝试:
Json.obj("_id" -> Json.obj("$in" -> ids)) // 1
Json.obj("_id.$oid" -> Json.obj("$in" -> ids)) // 2
Json.obj("_id" -> Json.obj("$oid" -> Json.obj("$in" -> ids))) // 3
第一个和第二个返回空列表,第三个失败,出现错误
断言10068无效运算符:$oid
我设法用以下方法解决了此问题:
val objectIds = ids.map(id => Json.obj("$oid" -> id))
val query = Json.obj("_id" -> Json.obj("$in" -> objectIds))
usersCollection.find(query).cursor[User].collect[List]()
由于play reactivemongo格式仅在“$oid”后跟字符串时才考虑BSONObjectID
implicit object BSONObjectIDFormat extends PartialFormat[BSONObjectID] {
def partialReads: PartialFunction[JsValue, JsResult[BSONObjectID]] = {
case JsObject(("$oid", JsString(v)) +: Nil) => JsSuccess(BSONObjectID(v))
}
val partialWrites: PartialFunction[BSONValue, JsValue] = {
case oid: BSONObjectID => Json.obj("$oid" -> oid.stringify)
}
}
尽管如此,我还是希望有一个更干净的解决方案。如果没有,我想这是一个很好的请求。注意:我的回复在ReactiveMongo邮件列表上的副本
首先,很抱歉我的回答耽搁了,我可能错过了你的问题。
Play ReactiveMongo无法自行猜测Json数组的值是ObjectID。这就是为什么您必须为每个id创建一个Json对象,如下所示:{“$oid”:“526FDA0F9205B1C000C82E34”}
。当ReactiveMongo Play插件看到第一个字段为$oid
的对象时,它将其视为ObjectId,以便驱动程序可以为此值发送正确的类型(BSONObjectID
)
实际上,这是一个更普遍的问题:JSON格式与BSON格式不完全匹配。对于数字类型(
BSONInteger
,BSONLong
,BSONDouble
),BSONRegex
,BSONDateTime
,以及BSONObjectID
)。您可以在MongoDB文档中找到更详细的信息:。我想知道这样将id转换为BSONObjectID是否更安全:
val ids: List[String] = ???
val bsonObjectIds = ids.map(BSONObjectID.parse(_)).collect{case Success(t) => t}
val objectIds = ids.map(id => Json.obj("$oid" -> id))
这将只生成有效的BSONObjectID(并丢弃无效的BSONObjectID)
如果您这样做:
val ids: List[String] = ???
val bsonObjectIds = ids.map(BSONObjectID.parse(_)).collect{case Success(t) => t}
val objectIds = ids.map(id => Json.obj("$oid" -> id))
如果导入
play.modules.reactivemongo.json,则您的objectid可能不是有效的objectid,这取决于字符串id是否真的是BSONObjectID的stringify版本
import play.modules.reactivemongo.json._
...
val ids: Seq[BSONObjectID] = ???
val selector = Json.obj("_id" -> Json.obj("$in" -> ids))
usersCollection.find(selector).cursor[User].collect[Seq]()
我尝试了以下方法,效果很好:
val listOfItems = BSONArray(51, 61)
val query = BSONDocument("_id" -> BSONDocument("$in" -> listOfItems))
val ruleListFuture = bsonFutureColl.flatMap(_.find(query, Option.empty[BSONDocument]).cursor[ResponseAccDataBean]().
collect[List](-1, Cursor.FailOnError[List[ResponseAccDataBean]]()))
为什么不Json.obj(“\u id”->Json.obj($in”->ids.map(BSONObjectID(\u)))
?@Dom,因为这样您就必须在隐式作用域中有Write[BSONObjectID]
的实例,而play reactivemongo
只提供部分实例。此外,编写一个文件感觉效率不高,因为在这种情况下,您将进行转换BSONValue
->JsValue
->BSONValue
。好的,理解您的意思,谢谢。在哪里注册BSONObjectIDFormat
?@harmeethinghtara您可以在任何地方拥有它。你需要做的是把它带到你需要做的任何地方。像import package.BSONObjectIDFormat
当我调用request.body.validate[User]
validate
方法时,这会自动执行吗?我的请求格式类似于{“\u id”:{“$oid”:“54fd4b7084071e6a6ab13cee”}“name”:“Akka”,“age”:30,“created”:1425886070013}