Использование построителя запросов MongoDBObject с Salat

Я пытаюсь предоставить API для поиска в коллекции MongoDB по различным критериям, включая полнотекстовый поиск. Поскольку это проект Scala (в Play FWIW), я использую Salat, абстракцию вокруг Касбы.

Следующий код работает нормально:

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

Однако в конечном итоге мне придется выполнять поиск по нескольким критериям и сортировать результаты по их оценке полнотекстового поиска, поэтому я изучил MongoDBObject от Casbah конструктор запросов (внизу).

Итак, я попытался воспроизвести вышеизложенное следующим образом:

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 в запрос. Но как только я это сделал, все заработало (как видно из первого фрагмента кода), и я подумал, что версия с построителем запросов эквивалентна.

Если на то пошло, вызов builder.result().toString() производит это:

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

Любая помощь в том, чтобы заставить построитель запросов работать на меня, была бы очень признательна.


person Vidya    schedule 12.07.2014    source источник
comment
то, что вы сделали, это оценка части запроса (первый аргумент), поэтому это критерий поиска, когда вы хотите, чтобы он был вторым аргументом для поиска.   -  person Asya Kamsky    schedule 12.07.2014


Ответы (1)


В вашем рабочем запросе вы передаете один DBObject для «предиката запроса» и второй DBObject для «полей» или «проекции» — find принимает второй необязательный аргумент, указывающий, какие поля возвращать, а в случае поиска $text есть специальное поле проекции $meta, которое позволяет вам получить оценку совпадающего документа, чтобы вы могли сортировать его.

В вашей попытке компоновщика вы добавляете проекцию DBObject к критериям запроса, и это дает вам ту же ошибку, которую вы видели раньше, когда опускаете компонент оценки в качестве второго аргумента для поиска.

Добавьте MongoDBObject("score" -> MongoDBObject("$meta" -> "textScore")) в качестве второго аргумента для поиска, как вы делали это раньше, и используйте builder для объединения нескольких критериев запроса.

Говоря простым языком JSON, вы вызываете find следующим образом:

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

когда вы действительно хотите назвать это так:

  db.coll.find( { "$text" : { "$search" : "Vidya"} } , { "score" : { "$meta" : "textScore"}} )
person Asya Kamsky    schedule 12.07.2014