ordered参数控制insertMany()错误处理方式:true时一错全停,false时仅跳过写入级错误(如重复键)并继续,但网络、权限等系统错误仍导致整体失败。

ordered参数决定批量插入是否“一错全停”
默认情况下,insertMany() 的 ordered 参数为 true,意味着只要某条文档插入失败(比如违反唯一索引、字段类型错误),后续所有文档都会被跳过,不执行。这不是“跳过错误项继续”,而是直接中断整个操作。
设你传入 10 条文档,第 4 条因 duplicate key 报错,那么第 5–10 条根本不会尝试插入——哪怕它们完全合法。
想让合法文档照常入库,必须显式设 ordered: false:
db.users.insertMany([
{ _id: 1, name: "Alice" },
{ _id: 2, name: "Bob" },
{ _id: 1, name: "Charlie" }, // 冲突
{ _id: 3, name: "Diana" }
], { ordered: false })
这时 MongoDB 会尽力插入每一条,冲突的跳过,其余成功写入。
ordered: false 不等于“忽略所有错误”
ordered: false 只影响“可恢复”的写入错误,比如重复键、文档过大、缺少必需字段等。它**不处理网络中断、权限拒绝、集合不可写、磁盘满等服务端或系统级错误**——这类错误仍会导致整个命令失败并返回错误。
- 唯一索引冲突 → 跳过该文档,继续下一条
-
$oid格式非法 → 跳过 - 单文档超 16MB → 命令直接报错(
BSONObj size too large),不执行任何插入 - 用户无
insert权限 → 直接报错,不执行
也就是说,ordered: false 是“尽力而为”,不是“容错万能开关”。它只对写操作层面的校验失败生效。
性能和结果处理差异明显
开启 ordered: false 后,MongoDB 必须逐条执行插入(无法合并优化),所以吞吐通常比 ordered: true 低 10%–30%,尤其在大量数据时更明显。
更重要的是:返回结果结构变了。你需要检查 result.insertedCount 和 result.writeErrors 字段来确认哪些失败了:
const result = db.users.insertMany([...], { ordered: false });
print(`成功插入 ${result.insertedCount} 条`);
if (result.writeErrors && result.writeErrors.length > 0) {
result.writeErrors.forEach(err => {
print(`索引 ${err.index} 失败:${err.errmsg}`);
});
}
注意:writeErrors 中的 index 是原始数组下标,不是插入后的顺序(因为可能有跳过)。
真正需要容错时,别只靠ordered
如果业务要求“必须确保某批数据中所有合法项都落库”,光设 ordered: false 还不够。常见坑包括:
- 多个客户端并发写同一集合,即使
ordered: false,也可能因竞态导致部分写入被覆盖或遗漏 - 某些错误(如
WriteConflict)在高并发下会被重试,但不体现在writeErrors里 - 应用层没检查
writeErrors,误以为全成功
稳妥做法是:先用 ordered: false 尝试,再根据 writeErrors 提取失败项,单独重试或记录日志。不要假设“设了 false 就万事大吉”。


















