2014-06-13 6 views
23

sto cercando di recuperare alcuni ID che esistono in un database Mongo con il seguente codice:pymongo.errors.CursorNotFound: id cursore '...' non valida sul server di

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

Tuttavia, dopo una breve mentre, io sono ricevere questo errore:

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

ho trovato questo article che si riferisce a questo problema. Tuttavia non mi è chiaro quale soluzione prendere. È possibile utilizzare find().batch_size(30)? Che cosa fa esattamente il comando sopra? Posso prendere tutti gli ID dei database usando batch_size?

risposta

44

Si sta verificando questo errore perché il cursore sta scadendo sul server (dopo 10 minuti di inattività).

Dalla documentazione pymongo:

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.

Quando si chiama il metodo collection.find interroga una collezione e restituisce un cursore per i documenti. Per ottenere i documenti si itera il cursore. Quando si esegue l'iterazione sul cursore, il driver sta effettivamente effettuando richieste al server MongoDB per recuperare più dati dal server. La quantità di dati restituiti in ciascuna richiesta è impostata dal metodo batch_size().

Dal 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.

Impostazione del batch_size un valore più basso vi aiuterà con gli errori errori di timeout, ma aumenterà il numero di volte che si sta andando ad ottenere l'accesso al server MongoDB per prendi tutti i documenti

La dimensione predefinita dei lotti:

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).

Non v'è alcun "diritto" dimensione universale batch. Dovresti testare con valori diversi e vedere qual è il valore appropriato per il tuo caso d'uso, cioè quanti documenti puoi elaborare in una finestra di 10 minuti.

L'ultima risorsa è che si imposta timeout=False. Ma devi essere sicuro che il cursore sia chiuso dopo aver completato l'elaborazione dei dati.

+0

Ho definito il batch_size su 50. Tuttavia ho ricevuto lo stesso errore pymongo.errors.CursorNotFound: id del cursore '' non valido al servizio er. Qual è il giusto valore che devo impostare batch_size? –

+0

@snakeplissken - aggiornato la mia risposta –

+0

Come posso essere sicuro con l'uso del timeout. Come posso essere sicuro che il cursore sia chiuso? –

26

Usa no_cursor_timeout=True come questo:

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

Si stava utilizzando il cursore oltre il time out (circa 10 minuti) in modo che il cursore non esiste più.

si dovrebbe scegliere un basso valore di batch_size per risolvere il problema:

(con Pymongo per esempio)

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

o

impostare il timeout su false col.find(timeout=False) e non dimenticare per chiudere il cursore alla fine.

+0

check out @Christian P risposta, è più dettagliato – hisi

Problemi correlati