【发布时间】:2019-09-10 14:56:39
【问题描述】:
在 node.js 中,我试图从一个 javascript 循环中将一个 json 对象插入到一个 mongodb 集合中,但在 _id 列上出现重复键错误。
{ MongoError: E11000 duplicate key error collection: app.Tab2017index: id dup key: { : ObjectId('5cbc813227b2ca2864b3c66a') }
这是我的 javascript 代码的一部分,它导致了错误。
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
const url = 'mongodb://localhost:27017';
const dbName = 'app';
var jsonData = {};
MongoClient.connect(url,{useNewUrlParser: true}, function(err, client) {
assert.equal(null, err);
if(err) { return console.dir(err); }
const db = client.db(dbName);
const collection = db.collection('Tab2017')
for (var i = 0; i < 5; i++) {
jsonData["test"] = "line";
console.log('LINE_'+i+'- '+JSON.stringify(jsonData));
collection.insertOne(jsonData, (err, result) => {
if(err) { console.dir(err); }
console.log('mongodb insert done');
})
}
})
以上代码在控制台显示错误,
D:\app\server\routes>node linmon.route-backup3.js
LINE_0- {"test":"line"}
LINE_1- {"test":"line","_id":"5cbc813227b2ca2864b3c66a"}
LINE_2- {"test":"line","_id":"5cbc813227b2ca2864b3c66a"}
LINE_3- {"test":"line","_id":"5cbc813227b2ca2864b3c66a"}
LINE_4- {"test":"line","_id":"5cbc813227b2ca2864b3c66a"}
mongodb insert done
-------------------------------------------
{ MongoError: E11000 duplicate key error collection: app.Tab2017 index: _id_ dup key: { : ObjectId('5cbc813227b2ca2864b3c66a') }
at Function.create (D:\app\server\node_modules\mongodb\node_modules\mongodb-core\lib\error.js:43:12)
at toError (D:\app\server\node_modules\mongodb\lib\utils.js:149:22)
at coll.s.topology.insert (D:\app\server\node_modules\mongodb\lib\operations\collection_ops.js:859:39)
at D:\app\server\node_modules\mongodb\node_modules\mongodb-core\lib\connection\pool.js:397:18
at process._tickCallback (internal/process/next_tick.js:61:11)
我没有插入 _id 列值并允许它由系统生成。这是 getindexes 的输出。
> db.Tab2017.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "app.Tab2017"
}
]
>
当我通过 mongo shell 命令行插入相同的对象时,它可以正常工作。看起来 javascript 不等待 mongodb 插入操作完成。
【问题讨论】:
-
Tab2017 集合中有没有_id 值等于 ObjectId('5cbb6bba88a60734c80302d2') 的文档?
-
是的,存在一个带有 ObjectId('5cbb6bba88a60734c80302d2') 的文档,它是从 Node.js 循环中的先前 insertOne 生成的。令人惊讶的是 mongodb 没有生成 _id ,它应该是系统生成的。
-
您需要显示重现问题的实际代码。最可能的原因是您有一个实例,并且您正在更改该实例中的一些数据以保存新项目,但没有意识到
_id值(可能在另一个操作中分配)在您实际执行的操作中没有改变正在做。但为了更正您的代码,您实际上需要显示导致问题的违规代码。 -
@Neil Lunn,我添加了部分代码。
-
啊。这是一个范围界定问题。
insertOne()实际上改变了jsonData对象以包含_id值。当然它保持不变,因为第一次迭代之后的每次迭代都已经包含_id字段并尝试“插入”它。基本上,您应该将jsonData = {}的声明或任何其他需要进行的有效初始化移动到 insidefor循环。您还应该发现insertMany(),它可以获取一组文档。后者基本上意味着您不需要将实际插入“循环”到 MongoDB。