MongoDB文档插入 #
一、文档概述 #
1.1 文档概念 #
文档(Document)是MongoDB中数据的基本单位,以BSON格式存储,类似于JSON对象。
javascript
// 简单文档
{
"_id": ObjectId("507f1f77bcf86cd799439011"),
"name": "John",
"age": 25,
"email": "john@example.com"
}
// 复杂文档
{
"_id": ObjectId("507f1f77bcf86cd799439012"),
"name": "Jane",
"address": {
"city": "Beijing",
"street": "Chaoyang Road"
},
"hobbies": ["reading", "swimming"],
"createdAt": ISODate("2024-01-01T00:00:00Z")
}
1.2 文档结构 #
text
文档结构
├── _id (主键,自动生成)
├── 字段名 (键)
│ └── 字段值 (值)
├── 嵌套文档
└── 数组字段
1.3 文档限制 #
| 限制 | 说明 |
|---|---|
| 大小 | 单个文档最大16MB |
| 嵌套深度 | 最多100层 |
| 字段名 | 不能包含$和. |
| _id | 必须唯一 |
二、insertOne方法 #
2.1 基本插入 #
javascript
// 插入单个文档
db.users.insertOne({
name: "John",
age: 25,
email: "john@example.com"
})
// 输出
{
"acknowledged": true,
"insertedId": ObjectId("65f1a2b3c4d5e6f7g8h9i0j1")
}
2.2 插入带_id的文档 #
javascript
// 指定_id
db.users.insertOne({
_id: 1,
name: "John",
age: 25
})
// 输出
{
"acknowledged": true,
"insertedId": 1
}
2.3 插入嵌套文档 #
javascript
// 插入嵌套文档
db.users.insertOne({
name: "John",
address: {
city: "Beijing",
street: "Chaoyang Road",
zipCode: "100000"
},
profile: {
avatar: "avatar.jpg",
bio: "Software Developer"
}
})
2.4 插入数组字段 #
javascript
// 插入数组字段
db.users.insertOne({
name: "John",
hobbies: ["reading", "swimming", "coding"],
scores: [85, 90, 78, 92],
education: [
{ school: "MIT", degree: "Bachelor", year: 2020 },
{ school: "Stanford", degree: "Master", year: 2022 }
]
})
2.5 插入选项 #
javascript
// 插入选项
db.users.insertOne(
{
name: "John",
age: 25
},
{
writeConcern: { w: "majority", j: true },
ordered: true
}
)
三、insertMany方法 #
3.1 批量插入 #
javascript
// 插入多个文档
db.users.insertMany([
{ name: "John", age: 25, city: "Beijing" },
{ name: "Jane", age: 28, city: "Shanghai" },
{ name: "Bob", age: 30, city: "Guangzhou" }
])
// 输出
{
"acknowledged": true,
"insertedIds": [
ObjectId("65f1a2b3c4d5e6f7g8h9i0j1"),
ObjectId("65f1a2b3c4d5e6f7g8h9i0j2"),
ObjectId("65f1a2b3c4d5e6f7g8h9i0j3")
]
}
3.2 有序插入 #
javascript
// 有序插入(遇到错误停止)
db.users.insertMany(
[
{ _id: 1, name: "John" },
{ _id: 1, name: "Jane" }, // 重复_id
{ _id: 2, name: "Bob" }
],
{ ordered: true } // 默认
)
// 第一个文档插入成功,第二个失败,第三个不会插入
// 报错:E11000 duplicate key error
3.3 无序插入 #
javascript
// 无序插入(遇到错误继续)
db.users.insertMany(
[
{ _id: 1, name: "John" },
{ _id: 1, name: "Jane" }, // 重复_id
{ _id: 2, name: "Bob" }
],
{ ordered: false }
)
// 第一个文档插入成功,第二个失败,第三个继续插入
// 报错:部分文档插入失败
3.4 大批量插入 #
javascript
// 大批量插入
const documents = []
for (let i = 0; i < 10000; i++) {
documents.push({
name: `user_${i}`,
age: Math.floor(Math.random() * 50) + 18,
createdAt: new Date()
})
}
db.users.insertMany(documents, { ordered: false })
四、insert方法(已废弃) #
4.1 基本用法 #
javascript
// insert方法(已废弃,不推荐使用)
db.users.insert({
name: "John",
age: 25
})
// 插入多个文档
db.users.insert([
{ name: "John", age: 25 },
{ name: "Jane", age: 28 }
])
注意: insert方法已废弃,推荐使用insertOne和insertMany。
五、批量写入 #
5.1 bulkWrite方法 #
javascript
// 批量写入操作
db.users.bulkWrite([
{
insertOne: {
document: { name: "John", age: 25 }
}
},
{
insertOne: {
document: { name: "Jane", age: 28 }
}
},
{
updateOne: {
filter: { name: "Bob" },
update: { $set: { age: 30 } }
}
},
{
deleteOne: {
filter: { name: "Alice" }
}
}
])
// 输出
{
"acknowledged": true,
"insertedCount": 2,
"insertedIds": {
"0": ObjectId("..."),
"1": ObjectId("...")
},
"matchedCount": 1,
"modifiedCount": 1,
"deletedCount": 1
}
5.2 批量插入优化 #
javascript
// 分批插入大量数据
const batchSize = 1000
const totalDocuments = 100000
for (let i = 0; i < totalDocuments; i += batchSize) {
const batch = []
for (let j = 0; j < batchSize && i + j < totalDocuments; j++) {
batch.push({
name: `user_${i + j}`,
age: Math.floor(Math.random() * 50) + 18,
createdAt: new Date()
})
}
db.users.insertMany(batch, { ordered: false })
}
六、插入选项 #
6.1 writeConcern选项 #
javascript
// 写关注级别
db.users.insertOne(
{ name: "John", age: 25 },
{
writeConcern: {
w: "majority", // 写入大多数节点
j: true, // 写入日志
wtimeout: 5000 // 超时时间
}
}
)
写关注级别:
| 级别 | 说明 |
|---|---|
| w: 0 | 不确认写入 |
| w: 1 | 确认主节点写入 |
| w: “majority” | 确认大多数节点写入 |
| w: n | 确认n个节点写入 |
6.2 ordered选项 #
javascript
// 有序插入
db.users.insertMany(
[...],
{ ordered: true } // 遇到错误停止
)
// 无序插入
db.users.insertMany(
[...],
{ ordered: false } // 遇到错误继续
)
七、插入验证 #
7.1 文档验证 #
javascript
// 创建带验证规则的集合
db.createCollection("users", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name", "email"],
properties: {
name: { bsonType: "string" },
email: { bsonType: "string" },
age: { bsonType: "int", minimum: 0 }
}
}
}
})
// 插入有效文档
db.users.insertOne({
name: "John",
email: "john@example.com",
age: NumberInt(25)
})
// 成功
// 插入无效文档
db.users.insertOne({
name: "John"
// 缺少email字段
})
// 报错:Document failed validation
7.2 绕过验证 #
javascript
// 绕过文档验证
db.users.insertOne(
{ name: "John" }, // 缺少email
{ bypassDocumentValidation: true }
)
八、插入错误处理 #
8.1 重复键错误 #
javascript
// 插入重复_id
db.users.insertOne({ _id: 1, name: "John" })
db.users.insertOne({ _id: 1, name: "Jane" })
// 报错:E11000 duplicate key error
// 使用try-catch处理
try {
db.users.insertOne({ _id: 1, name: "Jane" })
} catch (error) {
if (error.code === 11000) {
print("文档已存在")
}
}
8.2 验证错误 #
javascript
// 处理验证错误
try {
db.users.insertOne({
name: "John",
age: -1 // 年龄为负数
})
} catch (error) {
if (error.code === 121) {
print("文档验证失败: " + error.message)
}
}
8.3 网络错误 #
javascript
// 处理网络错误
try {
db.users.insertOne({ name: "John" })
} catch (error) {
if (error.name === "MongoNetworkError") {
print("网络错误: " + error.message)
}
}
九、插入性能 #
9.1 批量插入优化 #
javascript
// 推荐:批量插入
db.users.insertMany([...])
// 不推荐:循环单条插入
for (let i = 0; i < 1000; i++) {
db.users.insertOne({ name: `user_${i}` })
}
9.2 无序插入优化 #
javascript
// 无序插入更快
db.users.insertMany([...], { ordered: false })
9.3 写关注优化 #
javascript
// 降低写关注级别提高性能(开发环境)
db.users.insertOne(
{ name: "John" },
{ writeConcern: { w: 1 } }
)
// 高写关注级别(生产环境)
db.users.insertOne(
{ name: "John" },
{ writeConcern: { w: "majority", j: true } }
)
十、插入最佳实践 #
10.1 文档设计 #
javascript
// 推荐:扁平化设计
{
name: "John",
email: "john@example.com",
city: "Beijing",
createdAt: new Date()
}
// 避免:过度嵌套
{
user: {
profile: {
personal: {
info: {
name: "John"
}
}
}
}
}
10.2 字段命名 #
javascript
// 推荐:简短明确的字段名
{
name: "John",
email: "john@example.com",
createdAt: new Date()
}
// 避免:过长的字段名
{
user_full_name: "John",
user_email_address: "john@example.com",
user_account_creation_timestamp: new Date()
}
10.3 批量插入 #
javascript
// 推荐:合理分批
const batchSize = 1000
for (let i = 0; i < totalDocuments; i += batchSize) {
const batch = createBatch(i, batchSize)
db.users.insertMany(batch, { ordered: false })
}
// 避免:一次性插入过多
db.users.insertMany(hugeArray) // 可能超出内存限制
十一、常见问题 #
11.1 文档过大 #
javascript
// 问题:文档超过16MB
db.users.insertOne({
data: largeData // 超过16MB
})
// 报错:document too large
// 解决:使用GridFS
db.fs.files.insertOne({
filename: "large_file.pdf",
length: NumberLong(104857600)
})
11.2 插入速度慢 #
javascript
// 原因:有序插入、高写关注、索引过多
// 解决:
// 1. 使用无序插入
db.users.insertMany([...], { ordered: false })
// 2. 降低写关注
db.users.insertOne({...}, { writeConcern: { w: 1 } })
// 3. 批量插入
db.users.insertMany([...])
11.3 内存不足 #
javascript
// 问题:批量插入导致内存不足
// 解决:分批插入
const batchSize = 1000
for (let i = 0; i < totalDocuments; i += batchSize) {
const batch = documents.slice(i, i + batchSize)
db.users.insertMany(batch, { ordered: false })
}
十二、总结 #
插入操作速查表:
| 方法 | 说明 | 示例 |
|---|---|---|
| insertOne | 插入单个文档 | db.coll.insertOne({…}) |
| insertMany | 插入多个文档 | db.coll.insertMany([…]) |
| bulkWrite | 批量写入 | db.coll.bulkWrite([…]) |
插入选项:
| 选项 | 说明 | 默认值 |
|---|---|---|
| ordered | 有序插入 | true |
| writeConcern | 写关注 | |
| bypassDocumentValidation | 绕过验证 | false |
下一步,让我们学习文档更新!
最后更新:2026-03-27