Amazon DocumentDB 文档插入 #
一、文档结构 #
1.1 文档格式 #
javascript
// 基本文档结构
{
"_id": ObjectId("65a1b2c3d4e5f67890123456"),
"name": "张三",
"age": 30,
"email": "zhangsan@example.com",
"createdAt": ISODate("2024-01-15T10:00:00Z")
}
1.2 数据类型 #
javascript
// 支持的数据类型
{
"stringField": "文本",
"intField": NumberInt(42),
"longField": NumberLong(123456789),
"doubleField": 3.14,
"boolField": true,
"dateField": new Date(),
"objectIdField": ObjectId(),
"arrayField": [1, 2, 3],
"objectField": { key: "value" },
"nullField": null,
"binaryField": BinData(0, "base64string")
}
1.3 _id字段 #
javascript
// _id字段规则
// - 每个文档必须有_id
// - _id值必须唯一
// - 如果不指定,自动生成ObjectId
// 自动生成
db.users.insertOne({ name: "张三" })
// _id: ObjectId("65a1b2c3d4e5f67890123456")
// 手动指定
db.users.insertOne({
_id: "user_001",
name: "张三"
})
二、insertOne - 插入单个文档 #
2.1 基本用法 #
javascript
// 插入单个文档
db.users.insertOne({
name: "张三",
age: 30,
email: "zhangsan@example.com",
createdAt: new Date()
})
// 返回结果
{
"acknowledged": true,
"insertedId": ObjectId("65a1b2c3d4e5f67890123456")
}
2.2 带选项插入 #
javascript
// 指定写关注
db.users.insertOne(
{ name: "李四", age: 25 },
{ writeConcern: { w: "majority" } }
)
// 有序插入
db.users.insertOne(
{ name: "王五" },
{ ordered: true }
)
2.3 嵌套文档插入 #
javascript
// 插入嵌套文档
db.users.insertOne({
name: "张三",
address: {
province: "北京",
city: "北京市",
district: "朝阳区",
street: "朝阳路100号"
},
contacts: {
phone: "13800138000",
email: "zhangsan@example.com"
}
})
2.4 数组字段插入 #
javascript
// 插入包含数组的文档
db.users.insertOne({
name: "张三",
tags: ["编程", "阅读", "游泳"],
education: [
{ school: "清华大学", degree: "本科", year: 2015 },
{ school: "北京大学", degree: "硕士", year: 2018 }
],
scores: [95, 88, 92, 85]
})
三、insertMany - 插入多个文档 #
3.1 基本用法 #
javascript
// 插入多个文档
db.users.insertMany([
{
name: "李四",
age: 25,
email: "lisi@example.com"
},
{
name: "王五",
age: 28,
email: "wangwu@example.com"
},
{
name: "赵六",
age: 32,
email: "zhaoliu@example.com"
}
])
// 返回结果
{
"acknowledged": true,
"insertedIds": [
ObjectId("65a1b2c3d4e5f67890123457"),
ObjectId("65a1b2c3d4e5f67890123458"),
ObjectId("65a1b2c3d4e5f67890123459")
]
}
3.2 有序与无序插入 #
javascript
// 有序插入(默认)- 遇到错误停止
db.users.insertMany(
[
{ _id: 1, name: "用户1" },
{ _id: 1, name: "用户2" }, // 重复ID,会报错
{ _id: 2, name: "用户3" } // 不会插入
],
{ ordered: true }
)
// 无序插入 - 继续插入其他文档
db.users.insertMany(
[
{ _id: 1, name: "用户1" },
{ _id: 1, name: "用户2" }, // 失败
{ _id: 2, name: "用户3" } // 会插入
],
{ ordered: false }
)
3.3 批量插入选项 #
javascript
// 完整选项
db.users.insertMany(
[
{ name: "用户A", status: "active" },
{ name: "用户B", status: "pending" }
],
{
ordered: false,
writeConcern: { w: "majority", wtimeout: 5000 }
}
)
四、批量插入技巧 #
4.1 分批插入 #
javascript
// 大数据量分批插入
function batchInsert(collection, documents, batchSize = 1000) {
for (let i = 0; i < documents.length; i += batchSize) {
const batch = documents.slice(i, i + batchSize);
collection.insertMany(batch, { ordered: false });
print(`Inserted batch ${Math.floor(i / batchSize) + 1}`);
}
}
// 使用示例
const users = [];
for (let i = 0; i < 10000; i++) {
users.push({
name: `用户${i}`,
age: Math.floor(Math.random() * 50) + 18,
createdAt: new Date()
});
}
batchInsert(db.users, users, 1000);
4.2 使用脚本批量插入 #
javascript
// 从CSV导入
const csvData = `name,age,email
张三,30,zhangsan@example.com
李四,25,lisi@example.com
王五,28,wangwu@example.com`;
const documents = csvData.split('\n').slice(1).map(line => {
const [name, age, email] = line.split(',');
return {
name,
age: parseInt(age),
email,
createdAt: new Date()
};
});
db.users.insertMany(documents);
4.3 从其他集合复制 #
javascript
// 复制数据到新集合
db.source.find().forEach(function(doc) {
db.destination.insertOne(doc);
});
// 使用聚合管道复制
db.source.aggregate([
{ $match: { status: "active" } },
{ $out: "active_users" }
]);
五、错误处理 #
5.1 重复键错误 #
javascript
// 处理重复键错误
try {
db.users.insertOne({
_id: 1,
name: "张三"
});
} catch (error) {
if (error.code === 11000) {
print("文档已存在,跳过插入");
} else {
throw error;
}
}
5.2 验证错误 #
javascript
// 处理验证错误
try {
db.users.insertOne({
name: "张三",
email: "invalid-email" // 不符合验证规则
});
} catch (error) {
if (error.code === 121) {
print("文档验证失败: " + error.message);
}
}
5.3 写入错误 #
javascript
// 处理写入错误
try {
db.users.insertMany(
[
{ _id: 1, name: "用户1" },
{ _id: 1, name: "用户2" }
],
{ ordered: false }
);
} catch (error) {
print("部分文档插入失败");
print("成功数量: " + error.result.result.nInserted);
print("错误详情: " + JSON.stringify(error.result.result.writeErrors));
}
六、性能优化 #
6.1 批量大小优化 #
text
批量插入建议:
├── 批量大小:1000-5000文档
├── 单批大小:不超过16MB
├── 使用无序插入提高性能
└── 监控网络和内存使用
6.2 索引影响 #
javascript
// 插入前考虑索引
// 索引会降低插入速度
// 查看索引
db.users.getIndexes()
// 大量数据导入时,可以先删除索引
db.users.dropIndexes()
// 导入后重建索引
db.users.createIndex({ email: 1 })
6.3 写关注优化 #
javascript
// 根据场景选择写关注
// 高性能场景
db.users.insertOne(
{ name: "张三" },
{ writeConcern: { w: 1 } } // 只确认主实例
)
// 高可靠场景
db.users.insertOne(
{ name: "张三" },
{ writeConcern: { w: "majority", j: true } }
)
七、实际应用场景 #
7.1 用户注册 #
javascript
// 用户注册
async function registerUser(userData) {
const user = {
email: userData.email,
password: hashPassword(userData.password),
name: userData.name,
status: "pending",
createdAt: new Date(),
updatedAt: new Date()
};
try {
const result = await db.users.insertOne(user);
return { success: true, userId: result.insertedId };
} catch (error) {
if (error.code === 11000) {
return { success: false, error: "邮箱已被注册" };
}
throw error;
}
}
7.2 日志记录 #
javascript
// 批量日志插入
const logBuffer = [];
const BUFFER_SIZE = 100;
function logEvent(event) {
logBuffer.push({
...event,
timestamp: new Date()
});
if (logBuffer.length >= BUFFER_SIZE) {
flushLogs();
}
}
function flushLogs() {
if (logBuffer.length === 0) return;
db.logs.insertMany(logBuffer, { ordered: false });
logBuffer.length = 0;
}
// 定期刷新
setInterval(flushLogs, 5000);
7.3 数据导入 #
javascript
// 从JSON文件导入
const fs = require('fs');
function importFromJSON(filePath, collection) {
const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
const batchSize = 1000;
for (let i = 0; i < data.length; i += batchSize) {
const batch = data.slice(i, i + batchSize);
collection.insertMany(batch, { ordered: false });
print(`Imported ${Math.min(i + batchSize, data.length)} / ${data.length}`);
}
}
importFromJSON('./users.json', db.users);
八、最佳实践 #
8.1 文档设计 #
text
设计建议:
├── 使用有意义的字段名
├── 保持字段命名一致
├── 避免过深的嵌套(建议不超过3层)
├── 考虑查询模式设计文档
└── 添加必要的索引
8.2 批量插入建议 #
text
批量插入最佳实践:
├── 使用insertMany代替循环insertOne
├── 合理设置批量大小
├── 使用无序插入提高性能
├── 处理错误和重试
└── 监控性能指标
8.3 错误处理建议 #
text
错误处理最佳实践:
├── 捕获并处理重复键错误
├── 处理验证错误
├── 记录失败文档
├── 实现重试机制
└── 监控错误率
九、总结 #
9.1 插入方法对比 #
| 方法 | 用途 | 特点 |
|---|---|---|
| insertOne | 插入单个文档 | 简单直接 |
| insertMany | 插入多个文档 | 批量高效 |
| bulkWrite | 批量混合操作 | 灵活强大 |
9.2 关键要点 #
text
插入操作要点:
├── 理解_id字段的作用
├── 选择合适的批量大小
├── 处理可能的错误
├── 优化写关注设置
└── 监控插入性能
下一步,让我们学习文档更新!
最后更新:2026-03-27