如何检查pymongo游标是否有查询结果

boh*_*717 31 python mongodb pymongo mongodb-query

我需要检查find语句是否返回非空查询.

我在做的是以下内容:

query = collection.find({"string": field})
if not query: #do something
Run Code Online (Sandbox Code Playgroud)

然后我意识到我的if语句从未执行过因为find返回游标,或者查询是否为空.

因此我检查了文档,找到了两种可以帮助我的方法:

  1. count(with_limit_and_skip=False) 其中(来自说明):

    返回此查询的结果集中的文档数.

    这似乎是一个很好的检查方法,但这意味着我需要计算光标中的所有结果,以确定它是否为零,对吧?有点贵吗?

  2. retrieved 其中(来自说明):

    到目前为止检索的文件数量.

    我在一个空的查询集上测试它并返回零,但它不清楚它做了什么,我不知道它是否适合我.

那么,检查查询是否find()返回空集的最佳方法(最佳实践)是什么?上面描述的方法之一是否适用于此目的?性能怎么样?还有其他方法吗?


需要明确的是:我需要知道查询是否为空,我想找到关于性能和pythonic的光标的最佳方法.

Voo*_*OFX 35

编辑:虽然在2014年这是真的,现代版本的pymongo和MongoDB已经改变了这种行为.买家要小心:

.count()是查找查询中返回的结果数的正确方法.该count()方法不会耗尽游标的迭代器,因此您可以.count()在迭代结果集中的项之前安全地进行检查.

MongoDB 2.4中计数方法的性能得到了极大的提高.唯一可以减慢你速度的count是,如果查询上有索引,或者没有.要查明您是否有查询索引,您可以执行类似的操作

query = collection.find({"string": field})
print query.explain()
Run Code Online (Sandbox Code Playgroud)

如果您BasicCursor在结果中看到,则需要在该string字段上为此查询添加索引.


编辑:正如@a​​lvapan指出的那样,pymongo在pymongo 3.7+中弃用了这个方法,现在更喜欢count_documents在单独的查询中使用.

item_count = collection.count_documents({"string": field})
Run Code Online (Sandbox Code Playgroud)

计算查询返回的项目数的正确方法是.retreived在迭代后检查查询计数器,或者首先enumerate查询查询:

# Using .retrieved
query = collection.find({"string": field})
for item in query:
    print(item)

print('Located {0:,} item(s)'.format(query.retrieved))
Run Code Online (Sandbox Code Playgroud)

或者,另一种方式:

# Using the built-in enumerate
query = collection.find({"string": field})
for index, item in enumerate(query):
    print(item)

print('Located {0:,} item(s)'.format(index+1))
Run Code Online (Sandbox Code Playgroud)

  • @VooDooNOFX,PyMongo 3.7 已弃用cursor.count(),并要求我们改用collection.count_documents()。然后我不知道查找游标中返回的结果数的新*正确*方法是什么。我们是否需要先使用“collection.count_documents(query_string)”检查数字,然后使用“collection.find(query_string)”才能获得真正的结果?但是新的方式需要我们查询两次,而旧的方式只需要查询一次,这看起来更好。 (3认同)

Bar*_*man 7

如何使用find_one而不是find?然后你可以检查你是否得到了结果或None.如果"string"被索引,则可以传递fields = {"string":1, "_id" :0},从而使其成为仅索引查询,这甚至更快.

  • 根据我的理解,你想知道的是你是否对查询有任何结果,这是正确的吗?如果是这种情况,find_one对于你的情况就足够了:如果它返回一个值,则意味着find()会找到至少一个结果,如果它返回"None",则意味着find()将返回0结果. (2认同)

Bip*_*kar 7

另一种解决方案是将游标转换为列表,如果游标没有任何数据,则为空列表,否则列表包含所有数据。

 doc_list = collection.find({}); #find all data
 have_list = True if len(list(doc_list)) else False;
Run Code Online (Sandbox Code Playgroud)