2014-06-13 2 views
23

Ich versuche, einige ids zu holen, die mit dem folgenden Code in einer Mongo Datenbank vorhanden ist:pymongo.errors.CursorNotFound: Cursor id '...' nicht gültig bei Server

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'] 

jedoch nach kurzem während ich bin diesen Fehler erhalten:

pymongo.errors.CursorNotFound: cursor id '...' not valid at server.

ich diesen article gefunden, die zu diesem Problem bezieht. Trotzdem ist mir nicht klar, welche Lösung zu wählen ist. Ist es möglich, find().batch_size(30) zu verwenden? Was genau macht der obige Befehl? Kann ich alle Datenbank-IDs mit batch_size übernehmen?

Antwort

44

Sie erhalten diesen Fehler, weil der Cursor auf dem Server (nach 10 Minuten Inaktivität) Zeitlimit ist.

Von der pymongo Dokumentation:

Cursors in MongoDB can timeout on the server if they’ve been open for a long time without any operations being performed on them. This can lead to an CursorNotFound exception being raised when attempting to iterate the cursor.

Beim Aufruf der Methode collection.find es eine Sammlung abfragt und es gibt einen Cursor auf die Dokumente. Um die Dokumente zu erhalten, iterieren Sie den Cursor. Wenn Sie über den Cursor iterieren, fordert der Treiber tatsächlich den MongoDB-Server auf, weitere Daten vom Server abzurufen. Die Menge der Daten, die bei jeder Anfrage zurückgegeben werden, wird durch die Methode batch_size() festgelegt.

Vom documentation:

Limits the number of documents returned in one batch. Each batch requires a round trip to the server. It can be adjusted to optimize performance and limit data transfer.

Einstellen der batch_size auf einen niedrigeren Wert werden Sie mit den Timeout-Fehler Fehler helfen, aber es wird die Anzahl der Male, erhöhen Sie die MongoDB bekommen sind für den Zugriff auf Server hol dir alle Dokumente.

Die Standard-Chargengröße:

For most queries, the first batch returns 101 documents or just enough documents to exceed 1 megabyte. Batch size will not exceed the maximum BSON document size (16 MB).

Es gibt keine universelle "richtige" Losgröße. Sie sollten mit verschiedenen Werten testen und sehen, welcher Wert für Ihren Anwendungsfall geeignet ist, d. H. Wie viele Dokumente Sie in einem 10-Minuten-Fenster verarbeiten können.

Der letzte Ausweg wird sein, dass Sie timeout=False setzen. Sie müssen jedoch sicher sein, dass der Cursor geschlossen ist, nachdem Sie die Daten verarbeitet haben.

+0

Ich definierte die batch_size zu 50. Allerdings habe ich den gleichen Fehler pymongo.errors.CursorNotFound: Cursor-ID '' nicht gültig bei serv er. Was ist der richtige Wert, den ich Batch_size einstellen muss? –

+0

@snakeplissken - aktualisiert meine Antwort –

+0

Wie kann ich sicher sein mit der Verwendung von Timeout. Wie kann ich sicher sein, dass der Cursor geschlossen ist? –

26

Verwenden no_cursor_timeout=True wie folgt aus:

cursor=db.images.find({}, {'id':1, 'image_path':1, '_id':0}, no_cursor_timeout=True) 
for i in cursor: 
    # ..... 
    # ..... 
cursor.close() # use this or cursor keeps waiting so ur resources are used up 
0

Sie haben den Cursor über die Zeit aus (ca. 10 Minuten), so dass der Cursor nicht mehr existiert verwenden.

sollten Sie einen niedrigen Wert von batch_size wählen das Problem zu beheben:

(mit Pymongo zum Beispiel)

col.find({}).batch_size(10) 

oder

das Timeout auf false gesetzt col.find(timeout=False) und nicht zu vergessen um den Cursor am Ende zu schließen.

+0

check out @Christian P Antwort, es ist detaillierter – hisi

Verwandte Themen