Full text search in Pymongo

2020-05-26 09:33发布

The upcoming MongoDB 2.4 supports full-text search.

We do this in the mongo shell with a command, such as

db.players.runCommand("text", {
    "search": "alice", 
    "project": {"name": 1, "_id": 0}, 
    "limit": 10})

Now when porting this to pymongo, we have to deal with the fact that runCommand isn't defined on the pymongo Collection class. I was able to figure out what the real command was, so this worked in the shell:

db.runCommand({
    "text": "players", 
    "search": "alice", 
    "project": {"name": 1, "_id": 0}, 
    "limit": 10})

which worked. But this doesn't exactly tell me how to get this to work in pymongo. I tried:

db.command({
    "text":"players", 
    "pipeline": [
        ("search","alice"), ("project",{"name":1,"_id":0}), ("limit",10)
    ]})

which did not work (it said "no search specified"). I also tried:

db.command({
    "text": "players", 
    "search": "alice", 
    "project": {"name": 1, "_id": 0}, 
    "limit":10})

which of course fails with: "no such cmd: project".

I can get things to work if I only use search and limit, for example

db.command({
    "text": "players", 
    "search": "alice",
    "limit": 10})

but I would like to use filter and project with pymongo. Has anyone gotten full-text search working with project and filter?

Aside: Maybe there's a nice way to infer the shape of a pymongo command from a shell command?

2条回答
家丑人穷心不美
2楼-- · 2020-05-26 10:09

Figured it out: pymongo uses keyword arguments for the additional command arguments:

db.command("text", "players", 
    search="alice", 
    project={"name": 1, "_id": 0}, 
    limit=10)

The reason for the odd error message "no such cmd: project" is that Python's dictionaries are unordered, and the project key happened to be first when passed to mongo.

查看更多
姐就是有狂的资本
3楼-- · 2020-05-26 10:34

An alternative solution is to use OrderedDict. Assuming collection and query are given as variables while additional parameters such as limit, projection and others given in the dict 'params':

params_ord = OrderedDict()
params_ord['text'] = collection
params_ord['search'] = query
for k,v in params.iteritems():
    params_ord[k] = v
db.command(params_ord)
查看更多
登录 后发表回答