1. ホーム
  2. python

[解決済み] pymongo.errors.CursorNotFound: カーソルID '...' がサーバーで有効でない

2023-08-15 21:49:07

質問

以下のコードで、mongoデータベースに存在するいくつかのidを取得しようとしています。

client = MongoClient('xx.xx.xx.xx', xxx)
db = client.test_database
db = client['...']
collection = db.test_collection
collection = db["..."]


for cursor in collection.find({ "$and" : [{ "followers" : { "$gt" : 2000 } }, { "followers" : { "$lt" : 3000 } }, { "list_followers" : { "$exists" : False } }] }): 
    print cursor['screenname']
    print cursor['_id']['uid']
    id = cursor['_id']['uid']

しかし、しばらくすると、このようなエラーが発生します。

pymongo.errors.CursorNotFound: カーソルID '...' がサーバで有効ではありません。

私はこれを見つけました 記事 を見つけたのですが、その問題に言及しています。しかし、どのような解決策をとればよいのか、私にはわかりません。 可能なのは find().batch_size(30) ? 上記のコマンドは具体的に何をするのでしょうか?すべてのデータベースIDを batch_size ?

どのように解決するのですか?

このエラーが発生するのは、サーバー上でカーソルがタイムアウトしているためです(10分間操作されなかった場合)。

pymongoのドキュメントより。

MongoDB のカーソルは、何も操作されずに長い間開いているとサーバー上でタイムアウトすることがあります。 がタイムアウトすることがあります。この場合 を実行しようとすると CursorNotFound 例外を発生します。 例外が発生します。

を呼び出すと collection.find メソッドを呼び出すと、コレクションに問い合わせが行われ、ドキュメントへのカーソルが返されます。ドキュメントを取得するには、このカーソルを繰り返し実行します。カーソルを反復するとき、ドライバは実際に MongoDB サーバーにリクエストを出し、サーバーからさらにデータを取得します。各リクエストで返されるデータの量は batch_size() メソッドで設定します。

から ドキュメント :

1つのバッチで返されるドキュメントの数を制限します。各バッチ はサーバへのラウンドトリップを必要とします。この値は、パフォーマンスを最適化し、データ転送を制限するために パフォーマンスを最適化し、データ転送を制限するために調整することができます。

batch_sizeを低い値に設定すると、タイムアウトエラーのエラーは改善されますが、すべてのドキュメントを取得するためにMongoDBサーバーにアクセスする回数が増えます。

デフォルトのバッチサイズです。

ほとんどのクエリでは、最初のバッチは 101 個のドキュメントを返します。 のドキュメントを返します。バッチ サイズが BSON ドキュメント サイズの最大値 (16 MB) を超えることはありません。

普遍的な正しいバッチサイズは存在しません。さまざまな値でテストし、使用例 (たとえば、10 分間のウィンドウで処理できるドキュメントの数) に適した値を確認する必要があります。

最後の手段としては no_cursor_timeout=True . しかし、データの処理を終えたら、カーソルが閉じられていることを確認する必要があります。

を使わずに回避する方法 try/except :

cursor = collection.find(
     {"x": 1},
     no_cursor_timeout=True
)
for doc in cursor:
    # do something with doc
cursor.close()