How does one do a $text search on MongoDB with motor?

806 Views Asked by At

I have created an index for the db.

res = yield dbEmail["emails"].create_index([("subject", pymongo.TEXT)])

Now I'm trying to search on the created index by

dbEmail["emails"].find({$text: {$search: "dogs"}}, {score: {$meta: "textScore"}}).sort({score: {$meta: "textScore"}})

which I found doesn't work. The motor docs say the filter argument in db.collection.find(filter) is a SON object. When I try list_indexes() on my collection, they are SON objects too. But then

for index in (yield dbEmail["emails"].list_indexes()):
    searchResults = yield dbEmail["emails"].find(index)

also results in error. How do we $text search on index with motor?

edit: replying to Niel

My initial db collection looks like this:

emails = {"_id" : ObjectId("xxcxcdsfas"),"subject": "Joe owns a dog", "content": "Dogs are man's best friend", "likes": 60, "year": 2015,"language": "english"},
         {"_id" : ObjectId("xxcxcdsfas"),"subject": "Dogs eat cats and dog eats pigeons too", "content": "Cats are not evil", "likes": 30, "year": 2015,"language": "english"},
         {"_id" : ObjectId("xxcxcdsfas"),"subject": "Cats eat rats", "content": "Rats do not cook food", "likes": 55, "year": 2014, "language": "english"},
         {"_id" : ObjectId("xxcxcdsfas"), "subject": "Rats eat Joe", "content": "Joe ate a rat", "likes": 75, "year": 2014, "language": "english"} 

After creating the index (which is being created, I've verified), the final results that I require should be something like,

{ "_id" : ObjectId("xxcxcdsfas"), "subject" : "Dogs eat cats and dog eats pigeons too", "content" : "Cats are not evil", "likes" : 30, "year" : 2015, "language" : "english", "score" : 1 }
{ "_id" : ObjectId("xxcxcdsfas"), "subject" : "Joe owns a dog", "content" : "Dogs are man's best friend", "likes" : 60, "year" : 2015, "language" : "english", "score" : 0.6666666666666666 }

The first one has a higher score because dog appears twice in the subject, as opposed to once in the second one.

I checked that the index is valid with the following code:

    for item in (yield dbEmail["emails"].index_information()).items():
        print(item)

The response or index is below:

('_id_', {'v': 2, 'key': [('_id', 1)], 'ns': 'emailInfo.emails'})
('subject_text', {'v': 2, 'key': [('_fts', 'text'), ('_ftsx', 1)], 'ns': 'emailInfo.emails', 'weights': SON([('subject', 1)]), 'default_language': 'english', 'language_override': 'language', 'textIndexVersion': 3})
1

There are 1 best solutions below

1
Ankur On

Finally solved, the command "db.collection.command()" made it work,

searchResults = yield dbEmail.command({"find": "emails",
                                      "filter": {"$text": { "$search": "dogs"}}})