user3120928
user3120928

Reputation: 29

How to fix an issue with MongoDB score placed first in query by PyMongo and causing error

I have similar code as in PyMongo documentation on cursors here https://api.mongodb.org/python/current/api/pymongo/cursor.html

Here is the code from doc page.

cursor = db.test.find(
    {'$text': {'$search': 'some words'}},
    {'score': {'$meta': 'textScore'}})

When I run this code with Windows Python 2.7 PyMongo 3.0.3 and also 3.0.2 I get the following MongoDB error "OperationFailure: database error: Can't canonicalize query: BadValue unknown operator: $meta". Looking at the cause I was able reproduce this error if I use MongoDB client and put "{'score': {'$meta': 'textScore'}}" before "$text", like this.

db.test.find({ score: { $meta: "textScore" } }, { $text: { $search: "some words" }})

Back in Python, if I print dictionary with query keys I see "score" key first and "$text" key second. I guess this is causing PyMongo to form wrong query and subsequently an error in find methos.

Is there a work around for this issue?

Thanks

Upvotes: 3

Views: 454

Answers (2)

nickmilon
nickmilon

Reputation: 1372

you don't need a work around your first example should work I tested it with pymongo 3.0.3 and works just find.

db.test.find({'$text': {'$search': 'some words'}}, {'score': {'$meta': 'textScore'}})

Now, second example it fails because you switch the position of two positional arguments.

Talking about Python's unordered dictionaries makes no sense here because we are talking about two different dictionaries with a single key. I don't understand how you can get "score" key first and "$text" key second when we are talking about two dictionaries, except if you combined the two which is wrong, and your first try is not what you pasted here.

(*) There are cases with pymongo where you will need to use an ordered dictionary as in some complicated queries, in that case you should use a BSON object (see here) . But you don't need this in your case.

Upvotes: 1

user3120928
user3120928

Reputation: 29

I found the solution to my problem. I stopped using dictionary variable and formed query dictionary right inside of find method, like this.

db.test.find({'$text': {'$search': 'some text'}}, {'score': {'$meta': 'textScore'}})

Looks like doing this way causes an issue, even if I use OrderedDict.

search = {}
search['$text'] = {'$search': 'some text'}
search['score'] = { '$meta': 'textScore' }
db.test.find(search)

Upvotes: -1

Related Questions