I have a problem using Java API for MongoDB. I have created a query using Robomongo:
db.collection.find(
{$text : {$search : "\"expression\" keyword"}},
{score : {$meta : "textScore"}}
).sort({score : {$meta : "textScore"}})
Now I would like to create the same query using Java API:
DBObject searchCommand = new BasicDBObject(
"$text", new BasicDBObject("$search", "\"expression\" keyword")
).append(
"score", new BasicDBObject("'$meta'", "textScore")
);
DBObject sorting = new BasicDBObject(
"score", new BasicDBObject("'$meta'", "textScore")
);
DBCursor result = collection.find(searchCommand).sort(sorting);
The problem is that this code does not work. The query:
DBObject searchCommand = new BasicDBObject(
"$text", new BasicDBObject("$search", "\"expression\" keyword")
);
works perfectly. After appending the second part all results become invisible. What's more, this line:
DBCursor result = collection.find(searchCommand).sort(sorting);
throws MongoException (BadValue bad sort specification). When I remove sort() method invocation the Exception is not present, but still I don't have any results (if I append "score").
I have found a solution to this problem, but using Spring. I wouldn't like to use any other libraries. Also, I am a beginner in MongoDB. Thank you for your help and time, cheers.
UPDATE. Problem solved. Appending "score" to query searchCommand passed as first parameter of find() is wrong. "Score" should be passed in separate DBObject as the second parameter of find() method as follows:
DBObject search = new BasicDBObject(
"$text", new BasicDBObject("$search", "\"expression\" keyword")
);
DBObject project = new BasicDBObject(
"score", new BasicDBObject("$meta", "textScore")
);
DBObject sorting = new BasicDBObject(
"score", new BasicDBObject("$meta", "textScore")
);
DBCursor result = collection.find(search, project).sort(sorting);
You got really close, with what you have tried.
Note that in,
db.collection.find(
{$text : {$search : "\"expression\" keyword"}},
{score : {$meta : "textScore"}}
).sort({score : {$meta : "textScore"}})
{$text : {$search : "\"expression\" keyword"}}
- is the query
portion.
{score : {$meta : "textScore"}}
- is the projection
part.
In what you have tried to implement using the Java
driver,
DBObject searchCommand = new BasicDBObject(
"$text", new BasicDBObject("$search", "\"expression\" keyword")
).append(
"score", new BasicDBObject("'$meta'", "textScore")
);
would end up producing,
{$text:{$search:"\"expression\" keyword"},"score":{"meta":"textscore"}}
which is not equivalent to the native query. Even the intended projection
statement has been a part of the query
itself.
Note that, this ends up looking for a field named score
, since it has now become a part of the query
and not the projection
.
You can easily modify your DBObject
instances, to make it a part of the projection
parameter and it would work:
DBObject findCommand = new BasicDBObject(
"$text", new BasicDBObject("$search", "keyword")
);
DBObject projectCommand = new BasicDBObject(
"score", new BasicDBObject("$meta", "textScore"));
DBObject sortCommand = new BasicDBObject(
"score", new BasicDBObject("$meta", "textScore")
);
DBCursor result = collection.find(
findCommand ,projectCommand)
.sort(sortCommand );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With