insérer ou ignorer plusieurs documents en mongoDB
j'ai une collection dans laquelle tous mes documents ont au moins ces 2 champs, dire name
et url
(où url
est unique donc j'ai mis en place un index unique dessus). Maintenant, si j'essaie d'insérer un document avec un double url
, il va donner une erreur et arrête le programme. Je ne veux pas ce comportement, mais j'ai besoin de quelque chose comme mysql
insert or ignore
, de sorte que mongoDB ne doit pas insérer le document avec un double url
et continuer avec les documents suivants.
y a-t-il un paramètre que je peux passer à insert
commande pour atteindre ce comportement? Je fais généralement un lot d'inserts en utilisant pymongo
comme:
collection.insert(document_array)
Ici collection
est une collection et document_array
est un tableau de documents.
il y a donc un moyen que je puisse implémenter le insert or ignore
fonctionnalité pour un insert de document multiple?
7 réponses
mettre le continue_on_error
drapeau lors de l'appel de insert (). Note PyMongo pilote 2.1 et le serveur de la version 1.9.1 sont requises:
continue_on_error( optionnel): Si True, La base de données ne s'arrêtera pas traitement d'un encart en vrac si l'un d'eux échoue (par exemple en raison d'une duplication D'IDs). Cela rend l'insert en vrac se comporter de la même façon qu'une série d'inserts simples, sauf que lastError sera réglé si un insert échoue, pas seulement le dernier un. Si plusieurs erreurs se produisent, la plus récente sera être signalé par erreur().
essaye ceci:
try:
coll.insert(
doc_or_docs=doc_array,
continue_on_error=True)
except pymongo.errors.DuplicateKeyError:
pass
l'opération insert lancera toujours une exception si une erreur se produit dans l'insert (comme essayer d'insérer une valeur dupliquée pour un index unique), mais elle n'affectera pas les autres éléments du tableau. Vous pouvez ensuite avaler l'erreur comme indiqué ci-dessus.
utilisez insert_many (), et set ordered=False.
cela garantit que toutes les opérations d'écriture sont tentées, même s'il y a des erreurs: http://api.mongodb.org/python/current/api/pymongo/collection.html#pymongo.collection.Collection.insert_many
Pourquoi ne pas simplement mettre votre appel à .insert()
dans un try: ... except:
bloc et continuer si l'insertion échoue?
En outre, vous pouvez également utiliser un update()
appel upsert
drapeau. Plus de détails ici: http://www.mongodb.org/display/DOCS/Updating#Updating-update%28%29
si vous avez votre tableau de documents déjà en mémoire dans votre script python, pourquoi ne pas les insérer en itérant à travers eux, et simplement attraper ceux qui échouent lors de l'insertion en raison de l'index unique?
for doc in docs:
try:
collection.insert(doc)
except pymongo.errors.DuplicateKeyError:
print 'Duplicate url %s' % doc
où collection est une instance d'une collection créée à partir de vos instances de connexion/base de données et docs est le tableau de dictionnaires (documents) que vous passeriez actuellement à insérer.
Vous pouvez aussi décider quoi faire avec les doubles de clés qui violent votre index unique dans le except
bloc.
Il est fortement recommandé d'utiliser upsert
stat.update({'location': d['user']['location']}, \
{'$inc': {'count': 1}},upsert = True, safe = True)
Ici stat
est la collection si la position du visiteur est déjà présent dans la collection, count
est augmenté d'un, sinon count
est réglé sur 1
.
voici le lien pour la documentation http://www.mongodb.org/display/DOCS/Updating#Updating-UpsertswithModifiers
Ce que je fais :
- génère un tableau de MongoDB id je veux insérer (hachage de certaines valeurs dans mon cas)
- Enlever les Id (je suis à l'aide d'un Redis file d'attente bcoz la performance, mais vous pouvez interroger mongo)
- Insérez vos données nettoyées !
Redis est parfait pour cela, vous pouvez utiliser la mémoire Memcached ou Mysql, en fonction de vos besoins