web-dev-qa-db-fra.com

erreur mongodb curseur id pas valide

J'essaye de parcourir cette boucle:

for doc in coll.find()

Je reçois l'erreur suivante au 100 000e record. 

File "build\bdist.win32\Egg\pymongo\cursor.py", line 703, in next
File "build\bdist.win32\Egg\pymongo\cursor.py", line 679, in _refresh
File "build\bdist.win32\Egg\pymongo\cursor.py", line 628, in __send_message
File "build\bdist.win32\Egg\pymongo\helpers.py", line 95, in _unpack_response
pymongo.errors.OperationFailure: cursor id '1236484850793' not valid at server

que signifie cette erreur?

40
codious

Peut-être que votre curseur a expiré sur le serveur. Pour voir si cela pose problème, essayez de définir timeout = False`:

for doc in coll.find(timeout=False)

Voir http://api.mongodb.org/python/1.6/api/pymongo/collection.html#pymongo.collection.Collection.find

S'il s'agissait d'un problème de délai d'attente, une solution possible consiste à définir le batch_size (autres réponses).

38
Reto Aebersold
  • Définir le timeout=False est dangereux et ne doit jamais être utilisé, car la connexion au curseur peut rester ouverte pendant une durée illimitée, ce qui affectera les performances du système. Les documents font spécifiquement référence à la nécessité de fermer manuellement le curseur.
  • Définir batch_size sur un petit nombre fonctionnera, mais créera un gros problème de latence, car nous devons accéder à la base de données plus souvent que nécessaire.
    Par exemple:
    5 millions de documents avec un petit lot prendront des heures pour récupérer Les mêmes données qu’un batch_size par défaut retourne en quelques minutes.

Dans ma solution, il est obligatoire d'utiliser sort sur le curseur:

done = False
skip = 0
while not done:
    cursor = coll.find()
    cursor.sort( indexed_parameter ) # recommended to use time or other sequential parameter.
    cursor.skip( skip )
    try:
        for doc in cursor:
            skip += 1
            do_something()
        done = True
    except pymongo.errors.OperationFailure, e:
        msg = e.message
        if not (msg.startswith("cursor id") and msg.endswith("not valid at server")):
            raise
34
Oran

Régler timeout=False est une très mauvaise pratique. Un meilleur moyen de supprimer l’exception de temporisation id du curseur est d’estimer le nombre de documents que votre boucle peut traiter en 10 minutes et d’obtenir une taille de lot conservatrice. De cette façon, le client MongoDB (dans ce cas, PyMongo) devra interroger le serveur de temps en temps chaque fois que les documents du lot précédent sont épuisés. Cela maintiendra le curseur actif sur le serveur et vous serez toujours couvert par la protection contre l'expiration du délai de 10 minutes.

Voici comment vous définissez la taille de lot pour un curseur:

for doc in coll.find().batch_size(30):
    do_time_consuming_things()
25
jiehanzheng

vous devriez choisir une valeur basse de batch_size pour résoudre le problème:

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

voir ce qui suit répondre

0
HISI

Vous pouvez également forcer l'évaluation en utilisant:

for doc in list(coll.find())
0
laura112