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?
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).
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.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.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
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()
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
Vous pouvez également forcer l'évaluation en utilisant:
for doc in list(coll.find())