在node.js中,从一个JavaScript循环中,我试图将一个json对象插入一个mongodb集合中,但是在_id列上出现重复的键错误。
{MongoError:E11000重复键错误集合:app.Tab2017index: id dup键:{: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插入操作完成。
答案 0 :(得分:0)
_id
字段是唯一键字段。您不能在_id
列中插入重复的值。
例如,您在集合中存在一个_id值等于1的文档,而您尝试插入另一个具有相同_id值(1)的文档,则会收到 E11000重复键错误 >。
根据您的情况,在插入第二个文档时不会生成新的_id值,这会导致重复的错误。尝试为每个插入创建一个新的_id,或者不要传递_id值,以便MongoDB后端可以解决此问题。
答案 1 :(得分:0)
我自己解决了这个问题。 Nodejs执行异步操作,因此它完成了循环,但也不断插入mongodb集合中。我注意到,第一个操作始终会成功,而随后的插入操作会失败。 mongodb以某种方式为首次插入生成“ _id”值,并将相同的“ _id”保留在json对象中。这就是为什么它会引发重复错误。我刚刚添加了一行,以便在mongo插入之前从json对象中删除“ _id”,并且可以正常工作。
这是我修改的代码。
for (var i = 0; i < 5; i++) {
jsonData["test"] = "line";
**delete jsonData["_id"];**
console.log('LINE_'+i+'- '+JSON.stringify(jsonData));
collection.insertOne(jsonData, (err, result) => {
if(err) { console.dir(err); }
console.log('mongodb insert done');
})
}
答案 2 :(得分:0)
只需在插入对象之前删除_id字段即可。
delete jsonData["_id"];
如果您使用猫鼬,那就试试吧。
jsonData["_id"] = new mongoose.Types.ObjectId();
绝对可以解决您的问题,并且可以通过不丢失索引来保持唯一性。
答案 3 :(得分:0)
我遇到了类似的问题。问题在于范围(如上文 Neil Lunn 的评论中所述)。
我通过 Netlify 无服务器函数(Lambda 函数)将文档插入到集合中。我没有 DB-Schema。第一次进入工作正常。所有后续条目均失败。
失败的代码:
const mongodb = require('mongodb')
const MongoClient = mongodb.MongoClient
const myInitialDocument = { title: null }
function createClient (connectionString) {
const client = new MongoClient(
connectionString,
{ useNewUrlParser: true, useUnifiedTopology: true }
)
return client
}
exports.handler = async function (event) {
const dbClient = createClient('connection_string_to_db')
let entryToDb
try {
await dbClient.connect()
entryToDb = await dbClient.db().collection('somecollection').insertOne(myInitialDocument)
} catch (err) {
console.log(err)
}
dbClient.close()
return {
body: JSON.stringify(entryToDb)
}
}
上面的问题是 myInitialDocument
发生了变异,并且在初始调用之后它包含了 _id
。
更新有效的代码(没有 myInitialDocument
const):
const mongodb = require('mongodb')
const MongoClient = mongodb.MongoClient
function createClient (connectionString) {
const client = new MongoClient(
connectionString,
{ useNewUrlParser: true, useUnifiedTopology: true }
)
return client
}
exports.handler = async function (event) {
const dbClient = createClient('connection_string_to_db')
let entryToDb
try {
await dbClient.connect()
entryToDb = await dbClient.db().collection('somecollection').insertOne({ title: null })
} catch (err) {
console.log(err)
}
dbClient.close()
return {
body: JSON.stringify(entryToDb)
}
}
答案 4 :(得分:-2)
您可能需要删除索引,然后尝试插入。
db.collection.dropIndex()