W3docs

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

pip install pymongo

Connexion à 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: 64b3e2c1f0a1234567890abc

La 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-1

Si 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ésultatPropriétés clés
InsertOneResultinserted_id, acknowledged
InsertManyResultinserted_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: 6

Erreurs 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.
Was this page helpful?