【问题标题】:Using MongoDBObject Query Builder with Salat将 MongoDBObject Query Builder 与 Salat 一起使用
【发布时间】:2014-07-12 19:02:01
【问题描述】:

我正在尝试提供一个 API 来根据各种条件搜索 MongoDB 集合,包括全文搜索。由于这是一个 Scala 项目(在 Play FWIW 中),我使用的是 Salat,一个围绕 Casbah 的抽象。

以下代码可以正常工作:

MySalatDao
.find(MongoDBObject("$text" -> MongoDBObject("$search" -> "Vidya")), MongoDBObject("score" -> MongoDBObject("$meta" -> "textScore")))
.sort(orderBy = MongoDBObject("score" -> MongoDBObject("$meta" -> "textScore")))

但是,我最终需要根据多个条件进行搜索并按全文搜索分数对结果进行排序,因此我探索了 Casbah 的 MongoDBObject query builder functionality(在底部)。

所以我尝试像这样复制上面的内容:

val builder = MongoDBObject.newBuilder
builder += "$text" -> MongoDBObject("$search" -> "Vidya")
builder += "score" -> MongoDBObject("$meta" -> "textScore")
MySalatDao
.find(a.result())
.sort(orderBy = MongoDBObject("score" -> MongoDBObject("$meta" -> "textScore")))

这给出了以下异常:

com.mongodb.MongoException: Can't canonicalize query: BadValue must have $meta projection for all $meta sort keys
  at com.mongodb.QueryResultIterator.throwOnQueryFailure(QueryResultIterator.java:214)
  at com.mongodb.QueryResultIterator.init(QueryResultIterator.java:198)
  at com.mongodb.QueryResultIterator.initFromQueryResponse(QueryResultIterator.java:176)
  at com.mongodb.QueryResultIterator.<init>(QueryResultIterator.java:64)
  at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:86)
  at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:66)
.
.

我以前见过这个错误——当我没有在查询中包含score 组件时。但是一旦我这样做了,它就起作用了(如第一个代码 sn-p 所示),我认为带有查询生成器的版本是等效的。

就此而言,调用builder.result().toString() 会产生以下结果:

{ "$text" : { "$search" : "Vidya"} , "score" : { "$meta" : "textScore"}}

任何有关让查询生成器为我工作的帮助将不胜感激。

【问题讨论】:

  • 您所做的是使查询成为查询的一部分(第一个参数),因此它是一个搜索条件,当您希望它成为要查找的第二个参数时。

标签: mongodb scala casbah salat


【解决方案1】:

在您的工作查询中,您为“查询谓词”传递一个 DBObject,为“字段”或“投影”传递第二个 DBObject - find 接受第二个可选参数,指示要返回哪些字段,如果是 $text 搜索,有一个特殊的投影字段 $meta 可以让您取回匹配文档的分数,以便您可以对其进行排序。

在您的构建器尝试中,您将投影 DBObject 添加到查询条件中,这会导致您在忽略分数组件作为要查找的第二个参数时看到的相同错误。

添加MongoDBObject("score" -&gt; MongoDBObject("$meta" -&gt; "textScore")) 作为第二个参数以像以前一样查找,并使用builder 组合多个查询条件。

在简单的 JSON 术语中,您是这样调用 find 的:

  db.coll.find( { "$text" : { "$search" : "Vidya"} , "score" : { "$meta" : "textScore"}} )

当你真的想这样称呼它时:

  db.coll.find( { "$text" : { "$search" : "Vidya"} } , { "score" : { "$meta" : "textScore"}} )

【讨论】:

    猜你喜欢
    • 2015-04-30
    • 1970-01-01
    • 1970-01-01
    • 2020-02-08
    • 2021-12-27
    • 1970-01-01
    • 2022-06-30
    • 2014-08-08
    • 1970-01-01
    相关资源
    最近更新 更多