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}