Insertion dans MongoDB
Insérez des documents dans MongoDB avec Python et pymongo : insert_one, insert_many, ObjectId, gestion des erreurs et insertions en lot.
MongoDB stocke les données sous forme de documents — des objets flexibles similaires à JSON qui peuvent contenir des champs imbriqués et des tableaux. Ce chapitre vous explique comment insérer un document à la fois avec insert_one(), insérer plusieurs documents en un seul appel avec insert_many(), comprendre le champ _id généré automatiquement, gérer les erreurs de clé dupliquée et choisir entre les insertions en lot ordonnées et non ordonnées.
Prérequis
- Python 3.8 ou version ultérieure installé.
- Un serveur MongoDB en cours d'exécution (local ou distant). Si vous ne l'avez pas encore configuré, consultez MongoDB — Premiers pas.
- Une base de données et une collection prêtes à l'emploi. Consultez MongoDB — Créer une base de données et MongoDB — Créer une collection si vous avez besoin d'un rappel.
- Le pilote
pymongoinstallé :
pip install pymongoConnexion à MongoDB
Importez MongoClient et ouvrez une connexion avant d'effectuer toute opération d'insertion. Lorsque MongoDB s'exécute localement avec les paramètres par défaut, vous pouvez appeler MongoClient() sans arguments :
from pymongo import MongoClient
client = MongoClient() # connects to localhost:27017
db = client["bookstore"] # database (created on first write)
books = db["books"] # collection (created on first write)Pour vous connecter à un serveur distant ou à Atlas, passez un URI de connexion :
client = MongoClient("mongodb://username:password@hostname:27017/")MongoClient maintient un pool de connexions en interne, vous devez donc créer un seul client par application et le réutiliser pour toutes les opérations.
Insérer un seul document avec insert_one()
insert_one() ajoute un document à une collection et renvoie un objet InsertOneResult. La propriété la plus utile de cet objet est inserted_id, qui contient l'_id attribué au nouveau document.
from pymongo import MongoClient
client = MongoClient()
books = client["bookstore"]["books"]
document = {
"title": "The Pragmatic Programmer",
"author": "David Thomas",
"year": 1999,
"in_stock": True,
}
result = books.insert_one(document)
print("Inserted _id:", result.inserted_id)Exemple de sortie :
Inserted _id: 64b3e2c1f0a1234567890abcLa valeur exacte de l'_id sera différente à chaque fois — MongoDB génère un ObjectId unique, sauf si vous fournissez votre propre _id.
Comprendre le champ _id
Chaque document MongoDB doit avoir un champ _id. Si vous n'en incluez pas, le pilote génère automatiquement une valeur bson.ObjectId. Un ObjectId est une valeur de 12 octets qui encode :
- un horodatage Unix sur 4 octets (en secondes),
- une valeur aléatoire sur 5 octets unique à la machine et au processus,
- un compteur incrémental sur 3 octets.
Cela signifie que les valeurs ObjectId sont globalement uniques et approximativement ordonnées chronologiquement, sans aucune coordination entre les serveurs.
Vous pouvez fournir votre propre _id si vous disposez d'une clé unique naturelle (par exemple, un ISBN) :
result = books.insert_one({
"_id": "978-0-13-468599-1",
"title": "The Pragmatic Programmer",
"author": "David Thomas",
"year": 1999,
})
print("Inserted _id:", result.inserted_id)
# Inserted _id: 978-0-13-468599-1Si vous insérez un deuxième document avec le même _id, MongoDB lève une DuplicateKeyError (voir Gestion des erreurs ci-dessous).
Insérer plusieurs documents avec insert_many()
insert_many() accepte une liste de documents et les insère tous en un seul aller-retour réseau. Elle renvoie un InsertManyResult dont l'attribut inserted_ids contient la liste des valeurs _id attribuées dans l'ordre d'insertion.
from pymongo import MongoClient
client = MongoClient()
books = client["bookstore"]["books"]
new_books = [
{"title": "Clean Code", "author": "Robert C. Martin", "year": 2008},
{"title": "Refactoring", "author": "Martin Fowler", "year": 1999},
{"title": "Design Patterns", "author": "Gang of Four", "year": 1994},
]
result = books.insert_many(new_books)
print("Inserted IDs:", result.inserted_ids)Exemple de sortie :
Inserted IDs: [ObjectId('...'), ObjectId('...'), ObjectId('...')]Insertions ordonnées et non ordonnées
Par défaut, insert_many() utilise le mode ordonné : les documents sont insérés un par un dans l'ordre de la liste, et le traitement s'arrête à la première erreur.
Passez ordered=False pour le mode non ordonné : MongoDB tente l'insertion de chaque document indépendamment et collecte toutes les erreurs avant de lever une exception. C'est plus rapide pour les grands lots où vous attendez des doublons et souhaitez ignorer les documents problématiques plutôt qu'abandonner tout le lot.
from pymongo import MongoClient
from pymongo.errors import BulkWriteError
client = MongoClient()
books = client["bookstore"]["books"]
# Two documents with duplicate _id values mixed in
docs = [
{"_id": 1, "title": "Book A"},
{"_id": 2, "title": "Book B"},
{"_id": 1, "title": "Duplicate — will fail"}, # duplicate _id
{"_id": 3, "title": "Book C"},
]
try:
result = books.insert_many(docs, ordered=False)
print("Inserted:", result.inserted_ids)
except BulkWriteError as e:
# inserted_ids still shows the documents that succeeded
print("Some inserts failed:", e.details["nInserted"], "succeeded")
for err in e.details["writeErrors"]:
print(" Error on index", err["index"], "—", err["errmsg"])Avec ordered=False, Book A, Book B et Book C sont insérés même si le doublon échoue. Avec ordered=True (par défaut), le traitement s'arrêterait au troisième document et Book C ne serait jamais inséré.
Gestion des erreurs
Erreur de clé dupliquée
Insérer un document dont l'_id (ou tout champ couvert par un index unique) existe déjà lève une pymongo.errors.DuplicateKeyError :
from pymongo import MongoClient
from pymongo.errors import DuplicateKeyError
client = MongoClient()
books = client["bookstore"]["books"]
try:
books.insert_one({"_id": "isbn-001", "title": "First"})
books.insert_one({"_id": "isbn-001", "title": "Duplicate"}) # raises
except DuplicateKeyError as e:
print("Duplicate key:", e.details["keyValue"])Sortie :
Duplicate key: {'_id': 'isbn-001'}Erreurs de connexion
MongoClient() réussit même lorsque MongoDB n'est pas en cours d'exécution — l'erreur ne survient que lors d'une vraie requête. Encapsulez les opérations d'insertion dans un try/except pour gérer les échecs de connexion de manière élégante :
from pymongo import MongoClient
from pymongo.errors import ConnectionFailure, PyMongoError
client = MongoClient(serverSelectionTimeoutMS=3000)
try:
result = books.insert_one({"title": "Test"})
print("Inserted:", result.inserted_id)
except ConnectionFailure:
print("Could not reach MongoDB server.")
except PyMongoError as e:
print("MongoDB error:", e)Vérifier le résultat
insert_one() et insert_many() renvoient toutes deux des objets résultat avec des propriétés utiles :
| Objet résultat | Propriétés clés |
|---|---|
InsertOneResult | inserted_id, acknowledged |
InsertManyResult | inserted_ids (liste), acknowledged |
acknowledged vaut True lorsque MongoDB a confirmé l'écriture. Il peut valoir False uniquement si vous utilisez un write concern non acquitté (w=0), qui ignore la confirmation pour une vitesse maximale au détriment de la certitude que l'écriture a réussi.
Exemple complet fonctionnel
Le script autonome suivant se connecte à un serveur MongoDB local, insère plusieurs documents et affiche les résultats :
from pymongo import MongoClient
from pymongo.errors import DuplicateKeyError, BulkWriteError
DB_NAME = "demo_bookstore"
COL_NAME = "books"
def main():
client = MongoClient(serverSelectionTimeoutMS=3000)
# Verify connectivity
client.admin.command("ping")
print("Connected to MongoDB")
col = client[DB_NAME][COL_NAME]
col.drop() # start fresh for this demo
# --- insert_one ---
result = col.insert_one({
"_id": "isbn-001",
"title": "The Pragmatic Programmer",
"author": "David Thomas",
"year": 1999,
})
print("insert_one _id:", result.inserted_id)
# --- insert_many ---
result = col.insert_many([
{"title": "Clean Code", "author": "Robert C. Martin", "year": 2008},
{"title": "Refactoring", "author": "Martin Fowler", "year": 1999},
{"title": "Design Patterns", "author": "Gang of Four", "year": 1994},
])
print("insert_many IDs:", result.inserted_ids)
# --- duplicate key ---
try:
col.insert_one({"_id": "isbn-001", "title": "Duplicate"})
except DuplicateKeyError:
print("Caught DuplicateKeyError as expected")
# --- unordered bulk insert ---
docs = [
{"_id": "isbn-002", "title": "Book A"},
{"_id": "isbn-001", "title": "Dup — will fail"}, # duplicate
{"_id": "isbn-003", "title": "Book C"},
]
try:
col.insert_many(docs, ordered=False)
except BulkWriteError as e:
print("Bulk insert: succeeded =", e.details["nInserted"],
", failed =", len(e.details["writeErrors"]))
print("Total documents:", col.count_documents({}))
# Clean up
client.drop_database(DB_NAME)
if __name__ == "__main__":
main()Sortie attendue :
Connected to MongoDB
insert_one _id: isbn-001
insert_many IDs: [ObjectId('...'), ObjectId('...'), ObjectId('...')]
Caught DuplicateKeyError as expected
Bulk insert: succeeded = 2 , failed = 1
Total documents: 6Erreurs courantes
PyMongo modifie votre document
Lorsque vous passez un dict ordinaire à insert_one(), PyMongo ajoute une clé _id au dict original :
doc = {"title": "My Book"}
col.insert_one(doc)
print(doc) # {'title': 'My Book', '_id': ObjectId('...')}Si vous prévoyez de réutiliser le même dict (par exemple dans une boucle), passez une copie à la place : col.insert_one(doc.copy()).
Insertions massives : utilisez insert_many() plutôt qu'une boucle
Insérer 10 000 documents un par un génère 10 000 allers-retours réseau. Utilisez insert_many() pour les envoyer tous en une seule fois — c'est bien plus rapide pour les chargements en masse.
Si votre liste est très longue (des millions de documents), divisez-la en lots de quelques milliers pour ne pas dépasser la limite de taille BSON de 48 Mo par lot.
Les champs de date nécessitent des objets datetime, pas des chaînes
MongoDB stocke les dates au format BSON Date (millisecondes depuis l'époque). Utilisez datetime.datetime de Python pour les champs de date afin qu'ils soient stockés et interrogés correctement :
from datetime import datetime
col.insert_one({"title": "New Book", "published": datetime(2024, 3, 15)})Prochaines étapes
- MongoDB Find — interrogez et filtrez les documents que vous venez d'insérer.
- MongoDB Update — modifiez des documents existants.
- MongoDB Delete — supprimez des documents d'une collection.
- MongoDB Query — utilisez des opérateurs de comparaison et logiques pour filtrer les résultats.