6

playframework 2.2.0我有一个使用and设置的项目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

其中第一个和第二个返回空列表,第三个失败并出现错误assertion 10068 invalid operator: $oid

4

5 回答 5

3

注意:我在 ReactiveMongo 邮件列表上的回复副本。

首先,很抱歉我的回答延迟,我可能错过了你的问题。Play-ReactiveMongo 无法自行猜测 Json 数组的值是 ObjectId。这就是为什么你必须为每个看起来像这样的 id 创建一个 Json 对象{"$oid": "526fda0f9205b10c00c82e34"}:当 ReactiveMongo Play 插件看到第一个字段是的对象$oid时,它会将其视为 ObjectId,以便驱动程序可以发送该值的正确类型(BSONObjectID在这种情况下)。

这实际上是一个更普遍的问题:JSON 格式与 BSON 格式不完全匹配。数字类型(BSONIntegerBSONLongBSONDouble)、BSONRegexBSONDateTime和就是这种情况BSONObjectID。您可以在 MongoDB 文档中找到更详细的信息:http: //docs.mongodb.org/manual/reference/mongodb-extended-json/

于 2013-11-11T12:34:36.403 回答
0

我想知道以这种方式将 id 转换为 BSONObjectID 是否更安全:

val ids: List[String] = ???
val bsonObjectIds = ids.map(BSONObjectID.parse(_)).collect{case Success(t) => t}

如果您这样做,这只会生成有效的 BSONObjectID(并丢弃无效的):

val objectIds = ids.map(id => Json.obj("$oid" -> id))

您的 objectIds 可能不是有效的,具体取决于 string id 是否真的是 BSONObjectID 的 stringify 版本

于 2014-01-05T11:22:21.207 回答
0

我设法通过以下方式解决了它:

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)
  }
}

不过,我希望有一个更清洁的解决方案。如果没有,我想这会是一个不错的拉取请求。

于 2013-10-29T15:01:31.090 回答
0

我尝试了以下方法,它对我有用:

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]]()))
于 2020-07-10T12:30:14.233 回答
0

如果您play.modules.reactivemongo.json._在没有任何 $oid 格式化程序的情况下导入它。

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]()
于 2017-01-09T16:53:16.917 回答