node.js db.collection.insertOne-MongoError:E11000重复密钥错误集合:_id_dup

node.js db.collection.insertOne-MongoError:E11000重复密钥错误集合:_id_dup,node.js,mongodb,Node.js,Mongodb,在node.js中,从一个javascript循环中,我试图将一个json对象插入到一个mongodb集合中,但在_id列上出现重复键错误 {MongoError:E11000重复密钥错误集合:app.Tab2017index:id dup-key:{:ObjectId('5cbc813227b2ca2864b3c66a')} 这是我的javascript代码的一部分,它导致了错误 const MongoClient = require('mongodb').MongoClient; const

在node.js中,从一个javascript循环中,我试图将一个json对象插入到一个mongodb集合中,但在_id列上出现重复键错误

{MongoError:E11000重复密钥错误集合: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');             
                })              
        }     
  })
我没有插入_idcolumns值并允许系统生成它

> db.Tab2017.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "app.Tab2017"
        }
]
>

当我通过mongo shell命令行插入相同的对象时,它会正常工作。看起来javascript不会等待mongodb插入操作完成。

您可能需要删除索引,然后尝试插入

db.collection.dropIndex()

MongoDB中的
\u id
字段是唯一的键字段。不能在
\u id
列中插入重复的值

例如,集合中存在一个_id值等于1的文档,并且尝试插入另一个具有相同_id值(1)的文档,您将得到E11000重复键错误


在您的情况下,插入第二个文档时没有生成新的_id值,这会导致重复错误。请尝试为每次插入创建一个新的_id,或者不传递_id值,以便MongoDB后端处理此问题。

我自己解决了这个问题。Nodejs执行异步操作,以便完成循环t也一直插入到mongodb集合中。我注意到,第一个操作总是成功的,后续的插入总是失败的。mongodb为第一个插入生成“\u id”值,并在json对象中保持相同的“\u id”。这就是为什么它抛出重复错误的原因。我只添加了一行来删除“\u id”从mongo insert之前的json对象开始,它工作了

这是我修改过的代码

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');             
                })              
        } 
(变量i=0;i<5;i++)的

jsonData[“测试”]=“行”;
**删除jsonData[“_id”]**
log('LINE_'+i+'-'+JSON.stringify(jsonData));
collection.insertOne(jsonData,(err,result)=>{
if(err){console.dir(err);}
log('mongodb insert done');
})              
} 

在插入之前,只需从对象中删除_id字段

delete jsonData["_id"];
如果你用猫鼬,试试这个

jsonData["_id"] = new mongoose.Types.ObjectId();

这肯定会解决您的问题,您可以在不删除索引的情况下保持唯一性。

我有一个类似的问题。问题是范围(正如Neil Lunn在评论中提到的)

我通过Netlify无服务器函数(Lambda函数)将文档插入到集合中。我没有DB架构。第一个条目工作正常。所有后续条目都失败

失败的代码:

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
发生了变异,在初始调用之后,它包含了
\u id

已更新的有效代码(没有
myInitialDocument
const):


您在Tab2017集合中是否有任何id值等于ObjectId('5CB6BBBA88A60734C80302D2')的文档?是的,有一个文档存在ObjectId('5CB6BBBA88A60734C80302D2')),它是从Node.js循环中先前的insertOne生成的。令人惊讶的是,mongodb没有生成\u id,这应该不是系统生成的。您需要显示再现问题的实际代码。最可能的原因是您有一个实例,并且您正在更改该实例中的一些数据以保存新项,但没有实现
_id
值(可能在另一个操作中指定)在您实际执行的操作中不会更改。但为了更正代码,您实际上需要显示导致问题的错误代码。@Neil Lunn,我添加了部分代码。啊。这是一个范围问题。
insertOne()
实际上是对
jsonData
对象进行变异,以包含
\u id
值。当然,它保持不变,因为在第一次迭代之后的每个迭代都已经包含
\u id
字段并试图“插入”它。基本上,您应该移动
jsonData={}的声明
或任何其他需要在
for
循环中执行的有效初始化。您还应该发现
insertMany()
,它可以包含一个文档数组。后者基本上意味着您不需要“循环”对MongoDB的实际插入。_id是每个集合的默认索引,不能删除。我同意解释,但我不传递_id值。实际上最好在
for
循环中的
实例中声明类似
jsonData
的内容。如果要重用在范围外声明的对象,请执行以下操作:ke
insertOne({…jsonData})
基本上是对象数据的克隆,但不是相同的对象引用。原因是,不管是好是坏,前一段时间已经做出了决定,正确的做法确实是将传入的对象引用变异到基于
插入
的方法中,并添加
\u id
值,当一个值不存在时,将其赋值当前。使用新实例/克隆可避免删除
\u id
@usersam…您是如何获得删除它的\u id的?您能否显示要删除\u id的代码?
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)
  }
}
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)
  }
}