W3docs

MongoDB Insert

Lernen Sie, mit PyMongo einzelne und mehrere Dokumente in MongoDB einzufügen – inklusive Fehlerbehandlung, ObjectId und Bulk-Insert.

MongoDB speichert Daten als Dokumente — flexible, JSON-ähnliche Objekte, die verschachtelte Felder und arrays enthalten können. Dieses Kapitel zeigt Ihnen, wie Sie mit insert_one() ein Dokument auf einmal einfügen, mit insert_many() mehrere Dokumente in einem einzigen Aufruf einfügen, das automatisch generierte Feld _id verstehen, Fehler bei doppelten Schlüsseln behandeln und zwischen geordneten und ungeordneten Bulk-Inserts wählen.

Voraussetzungen

  • Python 3.8 oder höher ist installiert.
  • Ein laufender MongoDB-Server (lokal oder remote). Falls Sie noch keinen eingerichtet haben, lesen Sie MongoDB Get Started.
  • Eine Datenbank und eine Collection, die zur Verwendung bereit sind. Lesen Sie MongoDB Create Database und MongoDB Create Collection, wenn Sie eine Auffrischung benötigen.
  • Der pymongo-Treiber ist installiert:
pip install pymongo

Verbindung zu MongoDB herstellen

Importieren Sie MongoClient und öffnen Sie eine Verbindung, bevor Sie Insert-Operationen durchführen. Wenn MongoDB lokal mit Standardeinstellungen läuft, können Sie MongoClient() ohne Argumente aufrufen:

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)

Um eine Verbindung zu einem Remote-Server oder Atlas herzustellen, übergeben Sie einen Verbindungs-URI:

client = MongoClient("mongodb://username:password@hostname:27017/")

MongoClient verwaltet intern einen Verbindungspool, daher sollten Sie einen Client pro Anwendung erstellen und ihn für alle Operationen wiederverwenden.

Ein einzelnes Dokument mit insert_one() einfügen

insert_one() fügt ein Dokument zu einer Collection hinzu und gibt ein InsertOneResult-object zurück. Die nützlichste Eigenschaft dieses object ist inserted_id, das die _id enthält, die dem neuen Dokument zugewiesen wurde.

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)

Beispielausgabe:

Inserted _id: 64b3e2c1f0a1234567890abc

Der genaue _id-Wert unterscheidet sich jedes Mal — MongoDB generiert eine eindeutige ObjectId, sofern Sie keine eigene _id angeben.

Das Feld _id verstehen

Jedes MongoDB-Dokument muss ein _id-Feld haben. Wenn Sie keines angeben, generiert der Treiber automatisch einen bson.ObjectId-Wert. ObjectId ist ein 12-Byte-Wert, der Folgendes kodiert:

  • einen 4-Byte-Unix-Zeitstempel (Sekunden),
  • einen 5-Byte-Zufallswert, der für den Rechner und den Prozess eindeutig ist,
  • einen 3-Byte-inkrementierenden Zähler.

Das bedeutet, dass ObjectId-Werte ungefähr chronologisch geordnet und global eindeutig sind, ohne jegliche Koordination zwischen Servern.

Sie können Ihre eigene _id angeben, wenn Sie einen natürlichen eindeutigen Schlüssel haben (zum Beispiel eine 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

Wenn Sie ein zweites Dokument mit derselben _id einfügen, löst MongoDB einen DuplicateKeyError aus (siehe Fehlerbehandlung unten).

Mehrere Dokumente mit insert_many() einfügen

insert_many() akzeptiert eine Liste von Dokumenten und fügt sie alle in einem einzigen Netzwerk-Round-Trip ein. Es gibt ein InsertManyResult zurück, dessen Attribut inserted_ids die Liste der zugewiesenen _id-Werte in Einfügereihenfolge enthält.

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)

Beispielausgabe:

Inserted IDs: [ObjectId('...'), ObjectId('...'), ObjectId('...')]

Geordnete vs. ungeordnete Inserts

Standardmäßig verwendet insert_many() den geordneten Modus: Dokumente werden nacheinander in Listenreihenfolge eingefügt, und die Verarbeitung stoppt beim ersten Fehler.

Übergeben Sie ordered=False für den ungeordneten Modus: MongoDB versucht, jedes Dokument unabhängig voneinander zu verarbeiten, und sammelt alle Fehler, bevor eine Ausnahme ausgelöst wird. Dies ist schneller bei großen Batches, wenn Sie einige Duplikate erwarten und fehlerhafte Dokumente überspringen möchten, anstatt den gesamten Batch abzubrechen.

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"])

Mit ordered=False werden Book A, Book B und Book C eingefügt, auch wenn das Duplikat fehlschlägt. Mit ordered=True (dem Standard) würde die Verarbeitung beim dritten Dokument stoppen und Book C würde nie eingefügt werden.

Fehlerbehandlung

Fehler bei doppeltem Schlüssel

Das Einfügen eines Dokuments, dessen _id (oder ein anderes Feld, das durch einen eindeutigen Index abgedeckt wird) bereits vorhanden ist, löst pymongo.errors.DuplicateKeyError aus:

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"])

Ausgabe:

Duplicate key: {'_id': 'isbn-001'}

Verbindungsfehler

MongoClient() ist auch dann erfolgreich, wenn MongoDB nicht läuft — der Fehler tritt erst auf, wenn Sie eine echte Anfrage stellen. Umschließen Sie Insert-Operationen mit einem try/except, um Verbindungsfehler elegant zu behandeln:

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)

Das Ergebnis prüfen

Sowohl insert_one() als auch insert_many() geben Ergebnis-objects mit nützlichen Eigenschaften zurück:

Ergebnis-objectWichtige Eigenschaften
InsertOneResultinserted_id, acknowledged
InsertManyResultinserted_ids (Liste), acknowledged

acknowledged ist True, wenn MongoDB den Schreibvorgang bestätigt hat. Es kann nur dann False sein, wenn Sie ein unbestätigtes Write Concern (w=0) verwenden, das die Bestätigung zugunsten maximaler Geschwindigkeit überspringt – auf Kosten der Ungewissheit, ob der Schreibvorgang erfolgreich war.

Vollständiges Beispiel

Das folgende in sich abgeschlossene Skript verbindet sich mit einem lokalen MongoDB-Server, fügt mehrere Dokumente ein und gibt die Ergebnisse aus:

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()

Erwartete Ausgabe:

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

Häufige Fallstricke

PyMongo verändert Ihr Dokument

Wenn Sie ein einfaches dict an insert_one() übergeben, fügt PyMongo dem ursprünglichen dict einen _id-Schlüssel hinzu:

doc = {"title": "My Book"}
col.insert_one(doc)
print(doc)  # {'title': 'My Book', '_id': ObjectId('...')}

Wenn Sie dasselbe dict wiederverwenden möchten (zum Beispiel in einer Schleife), übergeben Sie stattdessen eine Kopie: col.insert_one(doc.copy()).

Große Inserts: verwenden Sie insert_many() statt einer Schleife

Das Einfügen von 10.000 Dokumenten einzeln erzeugt 10.000 Netzwerk-Round-Trips. Verwenden Sie insert_many(), um alle auf einmal zu senden — es ist um Größenordnungen schneller bei Massenladungen.

Wenn Ihre Liste sehr groß ist (Millionen von Dokumenten), teilen Sie sie in Batches von einigen Tausend auf, um das Limit von 48 MB BSON-Dokumentgröße pro Batch nicht zu überschreiten.

Datumsfelder benötigen datetime-objects, keine strings

MongoDB speichert Datumsangaben als BSON Date (Millisekunden seit der Epoche). Verwenden Sie Python's datetime.datetime für Datumsfelder, damit sie korrekt gespeichert und abgefragt werden:

from datetime import datetime
col.insert_one({"title": "New Book", "published": datetime(2024, 3, 15)})

Nächste Schritte

  • MongoDB Find — abfragen und filtern Sie die soeben eingefügten Dokumente.
  • MongoDB Update — vorhandene Dokumente ändern.
  • MongoDB Delete — Dokumente aus einer Collection entfernen.
  • MongoDB Query — Vergleichs- und logische Operatoren verwenden, um Ergebnisse zu filtern.
Was this page helpful?