I am attempting to provide an API to search a MongoDB collection on various criteria, including a full-text search. Since this is a Scala project (in Play FWIW), I am using Salat, an abstraction around Casbah.
The following code works fine:
MySalatDao
.find(MongoDBObject("$text" -> MongoDBObject("$search" -> "Vidya")), MongoDBObject("score" -> MongoDBObject("$meta" -> "textScore")))
.sort(orderBy = MongoDBObject("score" -> MongoDBObject("$meta" -> "textScore")))
However, I will eventually need to search on multiple criteria and sort the results by their full-text search score, so I explored Casbah's MongoDBObject query builder functionality (at bottom).
So I tried to replicate the above like this:
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")))
This gives the following exception:
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)
.
.
I've seen this error before--when I didn't include the score
component in the query. But once I did that, it worked (as seen in the first code snippet), and I thought the version with the query builder is equivalent.
For that matter, a call to builder.result().toString()
produces this:
{ "$text" : { "$search" : "Vidya"} , "score" : { "$meta" : "textScore"}}
Any help with getting the query builder to work for me would be much appreciated.