node.js db.collection.insertOne-MongoError:E11000重复键错误集合:_id_ dup

时间:2019-04-20 19:36:10

标签: node.js mongodb

在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插入操作完成。

5 个答案:

答案 0 :(得分:0)

MongoDB中的

_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()