web-dev-qa-db-ja.com

pymongoカーソルにクエリ結果があるかどうかを確認する方法

findステートメントが空でないクエリを返すかどうかを確認する必要があります。

私がやっていたことは次のとおりでした:

_query = collection.find({"string": field})
if not query: #do something
_

次に、ifがカーソルを返すため、クエリが空かどうかに関係なく、findステートメントが実行されないことに気付きました。

したがって、私は documentation をチェックし、私を助けることができる2つの方法を見つけました:

  1. count(with_limit_and_skip=False) which(説明から):

    このクエリの結果セットにあるドキュメントの数を返します。

    チェックするのに良い方法のように思えますが、これは、カーソル内のすべての結果をカウントして、ゼロかどうかを知る必要があることを意味しますよね?少し高い?

  2. retrieved which(説明から):

    これまでに取得されたドキュメントの数。

    空のクエリセットでテストし、ゼロを返しますが、それが何をするのかは明確ではなく、自分に適しているかどうかはわかりません。

それでは、find()クエリが空のセットを返すかどうかを確認する最良の方法(ベストプラクティス)はどれですか。上記の方法の1つがこの目的に適していますか?そして、パフォーマンスはどうですか?他の方法がありますか?


明確にするために:クエリが空かどうかを知る必要があり、パフォーマンスとPythonicに関して、カーソルを使用して最適な方法を見つけたいと思います。

29
boh717

[〜#〜] edit [〜#〜]これは2014年に当てはまりましたが、pymongoおよびMongoDBの最新バージョンこの動作を変更しました。バイヤーは注意してください:

.count()は、クエリで返される結果の数を見つける正しい方法です。 count()メソッドはカーソルの反復子を使い果たしません。そのため、結果セットの項目を反復処理する前に.count()チェックを安全に行うことができます。

Countメソッドのパフォーマンスは、MongoDB 2.4で大幅に改善されました。 countを遅くする可能性があるのは、クエリにインデックスが設定されているかどうかだけです。クエリにインデックスがあるかどうかを確認するには、次のようなことができます

query = collection.find({"string": field})
print query.explain()

結果にBasicCursorが表示される場合、このクエリのstringフィールドにインデックスが必要です。


[〜#〜] edit [〜#〜]:@alvapanが指摘したように、 pymongoは非推奨 pymongo 3.7のメソッド+そして今ではcount_documents別のクエリで。

item_count = collection.count_documents({"string": field})

クエリで返されたアイテムの数をカウントする正しい方法は、.retreivedクエリを反復処理した後、または最初の場所のenumerateクエリにカウンターします。

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

print('Located {0:,} item(s)'.format(query.retrieved))

または、別の方法:

# 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))
35
VooDooNOFX

findの代わりにfind_oneを使用するだけではどうですか?その後、結果が得られたか、Noneかを確認するだけです。また、「string」にインデックスが付けられている場合は、fields = {"string":1, "_id" :0}を渡すことができるため、インデックスのみのクエリにできます。これはさらに高速です。

7
Baruch Oxman

別の解決策は、カーソルをリストに変換することです。カーソルにデータがない場合は空のリスト、リストにはすべてのデータが含まれます。

 doc_list = collection.find({}); #find all data
 have_list = True if len(list(doc_list)) else False;
6
Biplab Malakar

私のテストから、最も簡単な方法は

if query.first():
    # do something

In [51]: %timeit query = MyMongoDoc.objects(); query.first()
100 loops, best of 3: 2.12 ms per loop

In [52]: %timeit query = MyMongoDoc.objects(); query.count()
100 loops, best of 3: 4.28 ms per loop

(MongoDB 2.6.7、2015-03-26を使用)

3
Arnaud Fouchet