The insertion of documents (insertOne, insertMany)
Document Insertion (insertOne, insertMany)
MongoDB provides two primary methods for document insertion: insertOne
and insertMany
. These methods are used to insert a single document and batch insert multiple documents, respectively, and are among the most fundamental and commonly used operations in MongoDB.
insertOne Method
The insertOne
method is used to insert a single document into a collection. Its basic syntax is as follows:
db.collection.insertOne(
<document>,
{
writeConcern: <document>
}
)
Here, <document>
is the document to be inserted, and writeConcern
is an optional write concern level.
Basic Example
// Insert a simple user document
db.users.insertOne({
name: "Zhang San",
age: 28,
email: "zhangsan@example.com",
hobbies: ["reading", "swimming"]
});
Upon successful insertion, MongoDB returns an object containing the following information:
{
acknowledged: true,
insertedId: ObjectId("5f8d8a7b9d8e7b6a9d8e7b6a")
}
Auto-Generated _id Field
If the inserted document does not specify an _id
field, MongoDB automatically generates a unique ObjectId
as the _id
:
db.products.insertOne({
name: "Laptop",
price: 5999,
category: "Electronics"
});
You can also explicitly specify the _id
:
db.products.insertOne({
_id: "prod001",
name: "Smartphone",
price: 3999
});
Error Handling
An error is thrown when inserting a document that violates a unique index constraint:
try {
db.users.insertOne({
_id: "user001",
name: "Li Si"
});
// Inserting a document with the same _id will fail
db.users.insertOne({
_id: "user001",
name: "Wang Wu"
});
} catch (e) {
print("Insertion failed: " + e);
}
insertMany Method
The insertMany
method is used to batch insert multiple documents and is more efficient than calling insertOne
multiple times. Its basic syntax is as follows:
db.collection.insertMany(
[ <document1>, <document2>, ... ],
{
writeConcern: <document>,
ordered: <boolean>
}
)
Basic Example
// Batch insert multiple users
db.users.insertMany([
{
name: "Wang Wu",
age: 32,
email: "wangwu@example.com"
},
{
name: "Zhao Liu",
age: 25,
email: "zhaoliu@example.com"
},
{
name: "Qian Qi",
age: 40,
email: "qianqi@example.com"
}
]);
Upon successful insertion, a result similar to the following is returned:
{
acknowledged: true,
insertedIds: [
ObjectId("5f8d8a7b9d8e7b6a9d8e7b6b"),
ObjectId("5f8d8a7b9d8e7b6a9d8e7b6c"),
ObjectId("5f8d8a7b9d8e7b6a9d8e7b6d")
]
}
ordered Parameter
The ordered
parameter defaults to true
, meaning documents are inserted in order. If one document fails to insert, subsequent documents will not be inserted:
try {
db.users.insertMany([
{ _id: 1, name: "User1" },
{ _id: 1, name: "User1 Duplicate" }, // This will fail
{ _id: 2, name: "User2" }
], { ordered: true });
} catch (e) {
print("Batch insertion error: " + e);
}
Setting ordered
to false
allows MongoDB to continue attempting to insert subsequent documents:
db.users.insertMany([
{ _id: 3, name: "User3" },
{ _id: 3, name: "User3 Duplicate" }, // This will fail
{ _id: 4, name: "User4" }
], { ordered: false });
Performance Considerations for Batch Insertion
For inserting large numbers of documents, insertMany
is more efficient than looping insertOne
. Here is a performance comparison example:
// Not recommended: Looping insertOne for 1000 documents
const start1 = new Date();
for (let i = 0; i < 1000; i++) {
db.test.insertOne({ value: i });
}
const end1 = new Date();
print("Loop insertOne time: " + (end1 - start1) + "ms");
// Recommended: Batch insert
const start2 = new Date();
const docs = [];
for (let i = 0; i < 1000; i++) {
docs.push({ value: i });
}
db.test.insertMany(docs);
const end2 = new Date();
print("insertMany time: " + (end2 - start2) + "ms");
Write Concern
Write concern specifies the level of acknowledgment MongoDB requires for a write operation to be considered successful. It can be specified during insertion:
// Wait for the write to be replicated to a majority of replica set members
db.products.insertOne(
{
name: "Bluetooth Headphones",
price: 299
},
{
writeConcern: { w: "majority", j: true, wtimeout: 5000 }
}
);
Common write concern options include:
w
: Number of nodes the write must propagate toj
: Whether to wait for journal writewtimeout
: Timeout in milliseconds
Practical Application Examples
Product Import in an E-Commerce System
// Get product data from an external source
const externalProducts = [
{
sku: "SKU1001",
name: "Wireless Mouse",
price: 129,
stock: 50,
categories: ["Electronics", "Computer Accessories"]
},
{
sku: "SKU1002",
name: "Mechanical Keyboard",
price: 399,
stock: 30,
categories: ["Electronics", "Computer Accessories"]
},
// More products...
];
// Batch import products
try {
const result = db.products.insertMany(externalProducts, {
ordered: false // Continue even if some products fail to import
});
print(`Successfully imported ${result.insertedCount} products`);
} catch (e) {
print(`Error during import: ${e}`);
}
User Registration System
function registerUser(userData) {
// Validate user data
if (!userData.username || !userData.password) {
throw new Error("Username and password cannot be empty");
}
// Check if the username already exists
const existingUser = db.users.findOne({ username: userData.username });
if (existingUser) {
throw new Error("Username already exists");
}
// Add registration timestamps
userData.createdAt = new Date();
userData.updatedAt = new Date();
// Insert the new user
const result = db.users.insertOne(userData);
// Return the newly created user ID
return result.insertedId;
}
// Usage example
try {
const newUserId = registerUser({
username: "newuser",
password: "securepassword123",
email: "newuser@example.com"
});
print(`User registered successfully, ID: ${newUserId}`);
} catch (e) {
print(`Registration failed: ${e.message}`);
}
Performance Optimization for Insert Operations
- Batch Insertion: Always prefer
insertMany
over loopinginsertOne
. - Adjust ordered Appropriately: For non-critical data, set
ordered: false
to improve throughput. - Disable Indexes: For one-time bulk data imports, disable indexes first and rebuild them afterward.
- Use Bulk Writes: For mixed operations (insert + update), consider using
bulkWrite
.
// Bulk write example
const bulkOps = [
{ insertOne: { document: { name: "Product A", price: 100 } } },
{ insertOne: { document: { name: "Product B", price: 200 } } },
{ updateOne: { filter: { name: "Product A" }, update: { $set: { stock: 50 } } } }
];
db.products.bulkWrite(bulkOps);
Common Issues and Solutions
Duplicate Key Error
When the _id
or a unique index field of the inserted document conflicts with an existing document, a duplicate key error is thrown. Solution:
try {
db.users.insertOne({
_id: "user123",
name: "Test User"
});
} catch (e) {
if (e.code === 11000) {
// Handle duplicate key error
print("User ID already exists");
// Optionally generate a new ID and retry
db.users.insertOne({
_id: ObjectId(), // Auto-generate new ID
name: "Test User"
});
} else {
throw e;
}
}
Document Size Limit
MongoDB has a 16MB limit per document. For data that may exceed this limit:
// Check document size
function getDocumentSize(doc) {
return Object.bsonsize(doc);
}
const largeDoc = { /* Very large document */ };
if (getDocumentSize(largeDoc) > 16 * 1024 * 1024) {
// Need to split the document or use GridFS
print("Document too large, needs splitting");
}
Slow Insertion Speed
If insertion speed is slower than expected, consider:
- Checking for excessive indexes
- Adjusting write concern level
- Using larger batch inserts
- Considering a sharded cluster to distribute write load
// Test insertion performance with different batch sizes
function testInsertPerformance(batchSize, totalDocs) {
const docs = [];
for (let i = 0; i < totalDocs; i++) {
docs.push({ value: i, data: "x".repeat(100) });
if (docs.length >= batchSize) {
db.perftest.insertMany(docs);
docs.length = 0; // Clear the array
}
}
if (docs.length > 0) {
db.perftest.insertMany(docs);
}
}
// Test different batch sizes
testInsertPerformance(100, 10000); // Insert 100 documents at a time
testInsertPerformance(500, 10000); // Insert 500 documents at a time
testInsertPerformance(1000, 10000); // Insert 1000 documents at a time
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:集合的创建与删除