Create a document (Create)
Creating Documents (Create)
Mongoose provides multiple methods to create documents and save them to a MongoDB database. The most commonly used methods are the save()
method of a model instance or directly using the create()
method of the model. These two methods each have their own advantages and disadvantages and are suitable for different scenarios.
Creating Documents Using the save()
Method
The save()
method is an instance method of a Mongoose document, used to save the document to the database. First, you need to create a model instance and then call the save()
method.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Define the schema
const userSchema = new Schema({
name: String,
age: Number,
email: String
});
// Create the model
const User = mongoose.model('User', userSchema);
// Create a document instance
const newUser = new User({
name: 'Zhang San',
age: 25,
email: 'zhangsan@example.com'
});
// Save the document
newUser.save()
.then(doc => {
console.log('Document saved successfully:', doc);
})
.catch(err => {
console.error('Save failed:', err);
});
The save()
method returns a Promise, allowing you to handle success and failure cases using then()
and catch()
. The advantage of this method is that it allows modifications to the document before saving, offering greater flexibility.
Creating Documents Using the create()
Method
The create()
method is a static method on the model that directly creates and saves a document. It is essentially a shortcut for new Model()
and save()
.
User.create({
name: 'Li Si',
age: 30,
email: 'lisi@example.com'
})
.then(doc => {
console.log('Document created successfully:', doc);
})
.catch(err => {
console.error('Creation failed:', err);
});
The create()
method can also accept an array for batch creation of documents:
User.create([
{ name: 'Wang Wu', age: 28, email: 'wangwu@example.com' },
{ name: 'Zhao Liu', age: 35, email: 'zhaoliu@example.com' }
])
.then(docs => {
console.log('Batch creation successful:', docs);
})
.catch(err => {
console.error('Batch creation failed:', err);
});
Inserting Multiple Documents
In addition to using the create()
method for batch insertion, you can also use the insertMany()
method. This method is more efficient than looping through save()
or create()
calls.
User.insertMany([
{ name: 'Qian Qi', age: 22, email: 'qianqi@example.com' },
{ name: 'Sun Ba', age: 40, email: 'sunba@example.com' }
])
.then(docs => {
console.log('Batch insertion successful:', docs);
})
.catch(err => {
console.error('Batch insertion failed:', err);
});
Validation and Hooks
When creating documents, Mongoose automatically performs validation as defined in the schema. If validation fails, the document will not be saved.
const invalidUser = new User({
name: 'Zhou Jiu',
age: 'Not a number', // This will trigger a validation error
email: 'zhoujiu@example.com'
});
invalidUser.save()
.then(doc => {
console.log('Document saved successfully:', doc);
})
.catch(err => {
console.error('Validation failed:', err.message);
// Output: "Validation failed: User validation failed: age: Cast to Number failed for value \"Not a number\" (type string) at path \"age\""
});
You can also use pre-save hooks to process documents before saving:
userSchema.pre('save', function(next) {
if (this.isNew) {
this.createdAt = new Date();
}
this.updatedAt = new Date();
next();
});
Atomicity and Transactions
In MongoDB 4.0+, you can use transactions to ensure atomicity across multiple operations. Mongoose also supports this feature:
const session = await mongoose.startSession();
session.startTransaction();
try {
const user1 = await User.create([{ name: 'User 1' }], { session });
const user2 = await User.create([{ name: 'User 2' }], { session });
await session.commitTransaction();
console.log('Transaction committed successfully');
} catch (error) {
await session.abortTransaction();
console.error('Transaction rolled back:', error);
} finally {
session.endSession();
}
Performance Considerations
When inserting a large number of documents, using insertMany()
is more efficient than looping through save()
or create()
calls. insertMany()
sends operations to the database in batches, reducing network round trips.
// Inefficient approach
for (let i = 0; i < 1000; i++) {
await User.create({ name: `User ${i}` });
}
// Efficient approach
const users = [];
for (let i = 0; i < 1000; i++) {
users.push({ name: `User ${i}` });
}
await User.insertMany(users);
Error Handling
When creating documents, you should properly handle potential errors. Common errors include validation errors and unique key conflicts.
try {
const user = await User.create({
email: 'existing@example.com' // Assume this email already exists and has a unique index
});
} catch (err) {
if (err.code === 11000) {
console.error('Email already exists');
} else {
console.error('Other error:', err);
}
}
Default Values and Auto-Population
You can define default values in the schema, which Mongoose will automatically populate when creating documents:
const productSchema = new Schema({
name: String,
price: Number,
inStock: { type: Boolean, default: true },
createdAt: { type: Date, default: Date.now }
});
const Product = mongoose.model('Product', productSchema);
const newProduct = await Product.create({ name: 'Product 1', price: 100 });
console.log(newProduct.inStock); // Output: true
console.log(newProduct.createdAt); // Output: Current time
Custom _id
By default, Mongoose automatically generates an _id
for each document. If you need a custom _id
, you can specify it during creation:
const customIdUser = await User.create({
_id: 'custom123',
name: 'Custom ID User'
});
console.log(customIdUser._id); // Output: "custom123"
Using Native Driver Methods
In some cases, you may need to bypass Mongoose features and directly use MongoDB native driver methods:
const result = await User.collection.insertOne({
name: 'Native Driver User',
age: 45
});
console.log(result.insertedId);
This method does not trigger Mongoose middleware or validation but offers higher performance.
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:模型的继承与扩展
下一篇:查询文档(Read)