#Inserting documents
Writing data comes first, because every query needs something to find. MongoDB has two insert methods: insertOne(doc) for a single document and insertMany([docs]) for a batch, which sends them in one round trip. Both return the _id of what they inserted; if a document has no _id, the client generates an ObjectId for it before sending.
The mental model for insertMany is a conveyor belt: documents go in one after another. By default it is ordered, so if one document fails (a duplicate _id, say), the belt stops there — earlier documents are already stored, later ones are never tried. With { ordered: false } the belt keeps going and reports every failure at the end. Either way, there is no rollback of the documents that succeeded: an insert batch is not a transaction.
This chapter's examples use one small users collection, inserted here, plus three more collections inserted at the end of this topic (products, movies, sales). One user, Grace, was "imported from a CSV" with her age stored as the string "47"; several later results depend on that.
db.users.insertOne({
_id: 1, name: "Alice", age: 28, city: "Toronto", email: "alice@example.com",
hobbies: ["reading", "chess", "hiking"],
address: { street: "12 King St", city: "Toronto", zip: "M5H" }
})
db.users.insertMany([
{ _id: 2, name: "Bob", age: 45, city: "New York", email: "bob@example.com",
hobbies: ["golf", "chess"], address: { city: "New York", zip: "10001" } },
{ _id: 3, name: "Chandra", age: 52, city: "Mumbai", email: "chandra@example.com",
hobbies: ["cricket", "cooking", "chess"], address: { city: "Mumbai", zip: "400001" } },
{ _id: 4, name: "Dana", age: 35, city: "London", email: null, hobbies: [] },
{ _id: 5, name: "Elif", age: 41, city: "Los Angeles", hobbies: ["surfing"] },
{ _id: 6, name: "Farid", age: 19, city: "Dubai", email: "farid@example.com" },
{ _id: 7, name: "Grace", age: "47", city: "Toronto", email: "GRACE@EXAMPLE.COM", hobbies: ["Reading"] }
]){ acknowledged: true, insertedId: 1 }
{
acknowledged: true,
insertedIds: { '0': 2, '1': 3, '2': 4, '3': 5, '4': 6, '5': 7 }
}insertOnesends Alice and replies withinsertedId: 1, the_idwe chose. Theuserscollection is created by this first write.insertManysends the other six in one request. The reply'sinsertedIdsmaps each document's position in the array ('0'to'5') to its_id, so you can tell which input became which document.- The documents deliberately differ: Dana has
email: nulland an emptyhobbiesarray, Elif has noemailfield at all, Farid has nohobbiesfield, and Grace'sageis a string. MongoDB accepted all of them without complaint, because nothing validates the shape. acknowledged: truemeans the server confirmed the write under the default write concern (majority of the replica set, which here is the one member). With{ writeConcern: { w: 0 } }you'd getacknowledged: falseand no confirmation at all (Write concern).
db.scratch.insertMany([{ _id: 1 }, { _id: 2 }])
db.scratch.insertMany([{ _id: 3 }, { _id: 1 }, { _id: 4 }])
db.scratch.insertMany([{ _id: 5 }, { _id: 1 }, { _id: 6 }], { ordered: false })
db.scratch.find(){ acknowledged: true, insertedIds: { '0': 1, '1': 2 } }
Uncaught:
MongoBulkWriteError: E11000 duplicate key error collection: ch16.scratch index: _id_ dup key: { _id: 1 }
Result: BulkWriteResult {
insertedCount: 1,
matchedCount: 0,
modifiedCount: 0,
deletedCount: 0,
upsertedCount: 0,
upsertedIds: {},
insertedIds: { '0': 3 }
}
Write Errors: [
WriteError {
err: {
index: 1,
code: 11000,
errmsg: 'E11000 duplicate key error collection: ch16.scratch index: _id_ dup key: { _id: 1 }',
errInfo: undefined,
op: { _id: 1 }
}
}
]
Uncaught:
MongoBulkWriteError: E11000 duplicate key error collection: ch16.scratch index: _id_ dup key: { _id: 1 }
Result: BulkWriteResult {
insertedCount: 2,
matchedCount: 0,
modifiedCount: 0,
deletedCount: 0,
upsertedCount: 0,
upsertedIds: {},
insertedIds: { '0': 5, '2': 6 }
}
Write Errors: [
WriteError {
err: {
index: 1,
code: 11000,
errmsg: 'E11000 duplicate key error collection: ch16.scratch index: _id_ dup key: { _id: 1 }',
errInfo: undefined,
op: { _id: 1 }
}
}
]
[ { _id: 1 }, { _id: 2 }, { _id: 3 }, { _id: 5 }, { _id: 6 } ]- The first batch inserts
_id1 and 2. - The second batch is ordered (the default).
_id: 3goes in, then_id: 1is a duplicate:MongoBulkWriteErrorwithE11000, and theResult:part showsinsertedCount: 1. The batch stopped, so_id: 4was never attempted. TheWrite Errorslist gives the failing position (index: 1) and the code11000. - The third batch is unordered.
_id: 5goes in,_id: 1fails, and the server carries on:_id: 6goes in too,insertedCount: 2, andinsertedIdshas positions'0'and'2'— position 1 is the one that failed. - The final
find()shows1, 2, 3, 5, 6: no4, and nothing was rolled back. Useordered: falsefor bulk loads where you want as many good documents as possible (it can also be faster, since the server may apply the batch in parallel); use the default when later documents depend on earlier ones. For all-or-nothing, wrap the inserts in a transaction.
products is the site's sample product list with reviews embedded, movies has arrays of genres, ratings and comments, and sales has a volume and a target per item:
db.products.insertMany([
{ _id: 1, name: "ThinkBook 14", category: "Electronics", subcategory: "Laptops", price: 899, stock: 12,
reviews: [ { reviewer: "Alice", rating: 5, comment: "Great keyboard" }, { reviewer: "Bob", rating: 3, comment: "Fan is loud" } ] },
{ _id: 2, name: "MacBook Air", category: "Electronics", subcategory: "Laptops", price: 1299, stock: 5,
reviews: [ { reviewer: "Bob", rating: 5, comment: "Silent and fast" }, { reviewer: "Alice", rating: 3, comment: "Too few ports" } ] },
{ _id: 3, name: "Pixel 10", category: "Electronics", subcategory: "Phones", price: 799, stock: 20,
reviews: [ { reviewer: "Alice", rating: 4, comment: "great camera" } ] },
{ _id: 4, name: "iPhone 17", category: "Electronics", subcategory: "Phones", price: 1099, stock: 0, reviews: [] },
{ _id: 5, name: "SQL Performance Explained", category: "Books", price: 39, stock: 50,
reviews: [ { reviewer: "Chandra", rating: 5, comment: "Must read for indexes" } ] },
{ _id: 6, name: "Designing Data-Intensive Applications", category: "Books", price: 49, stock: 35,
reviews: [ { reviewer: "Alice", rating: 5 }, { reviewer: "Dana", rating: 4, comment: "Dense but worth it" } ] },
{ _id: 7, name: "USB-C Charger", category: "Electronics", subcategory: "Accessories", price: 29, stock: 100,
reviews: [ { reviewer: "Alice", rating: 2, comment: "Stopped working" }, { reviewer: "Elif", rating: 4 } ] },
{ _id: 8, name: "Noise-cancelling Headphones", category: "Electronics", subcategory: "Accessories", price: 249, stock: 8,
reviews: [ { reviewer: "Bob", rating: 4 } ] }
]).insertedIds
db.movies.insertMany([
{ _id: 1, title: "Inception", year: 2010, genres: ["action", "thriller", "sci-fi"], ratings: [9, 8, 10], visitors: 1200,
comments: [ { user: "amy", text: "Mind-bending" }, { user: "raj", text: "Loved the score" }, { user: "lee", text: "Too long" } ] },
{ _id: 2, title: "Heat", year: 1995, genres: ["action", "thriller"], ratings: [8, 7], visitors: 800,
comments: [ { user: "raj", text: "Classic" } ] },
{ _id: 3, title: "Amelie", year: 2001, genres: ["comedy", "romance"], ratings: [9, 7], visitors: 500 },
{ _id: 4, title: "Up", year: 2009, genres: ["animation", "comedy"], ratings: [7, 10, 6], visitors: 1200 },
{ _id: 5, title: "Dune", year: 1984, genres: ["sci-fi"], ratings: [6, 5], visitors: 300 },
{ _id: 6, title: "Dune", year: 2021, genres: ["sci-fi", "adventure"], ratings: [8, 9], visitors: 1500 },
{ _id: 7, title: "Mad Max: Fury Road", year: 2015, genres: ["action", "adventure"], ratings: [10, 9, 8], visitors: 900 }
]).insertedIds
db.sales.insertMany([
{ _id: 1, item: "laptops", volume: 200, target: 180 },
{ _id: 2, item: "phones", volume: 195, target: 190 },
{ _id: 3, item: "chargers", volume: 120, target: 150 },
{ _id: 4, item: "books", volume: 90, target: 80 },
{ _id: 5, item: "headphones", volume: 190, target: 185 }
]).insertedIds{ '0': 1, '1': 2, '2': 3, '3': 4, '4': 5, '5': 6, '6': 7, '7': 8 }
{ '0': 1, '1': 2, '2': 3, '3': 4, '4': 5, '5': 6, '6': 7 }
{ '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 }- Each
insertMany(...)is followed by.insertedIds, which picks just that part of the reply so the output stays short: position →_idfor every document. - In
products, every document has an array of embedded review documents. Several later examples hinge on the fact that the MacBook Air and the USB-C Charger each have a review by Alice and a review with a high rating, but not in the same review. - In
movies, there are two films called "Dune" (for multi-key sorting), andUphas ratings[7, 10, 6], which matters for the$elemMatchexample. - In
sales,phonesandheadphonesbeat their targets only narrowly, which is what the$condexample in $expr: comparing fields is about.