Nodejs,mongodb在插入许多后更新数组

Posted

技术标签:

【中文标题】Nodejs,mongodb在插入许多后更新数组【英文标题】:Nodejs, mongodb updating array on after insert many 【发布时间】:2015-05-27 13:34:57 【问题描述】:

在 nodejs + mongodb 上使用一个简单的脚本遇到了一些奇怪的情况。

我正在从 csv 文件中读取数据,在对数据进行操作后,我想将数据保存到 mongodb 中。单次插入一切正常,但为了获得更好的性能,我想使用多次插入,所以这是我的脚本:

parser.on('readable', function()
 while(record = parser.read())
   ...
   // Saving data in a buffer
   buffer.push(
     'name': cleared_name,
     'source': source,
     'notes': notes,
     'address': address[0]
   )

   // If buffer is more that 100 or we rich end of csv file - insert data into mongodb
   if(buffer.length >= 100 || readAllLines) 
      db.collection('peoples').insert(buffer, w: 1, forceServerObjectId: false,  function(err, result) 
        lineCount -= result.insertedCount;

        // Close db connection if we insert all data
        if (lineCount === 0 && readAllLines) 
          db.close()
        
        // Lets check what is in buffer right now
        console.log(buffer)
        // Clear buffer  
        buffer.length = 0;
        buffer = [] // or delete buffer;
      );
    
 
)

插入 200 行后,mongodb 给我那个错误:

 AssertionError: "name":"MongoError","message":"insertDocument :: caused by :: 11000 E11000 duplicate key error index: databasename.peoples.$_id_ == null ...

缓冲区数组将包含该数据:

[ name: 'kelly',
source: 'Forbes.com',
notes: 'Scraped from box XX',
address: '104.236.115.138',
_id: 5565c77d8533c30967b5b278 ,
 name: 'kas',
source: 'Forbes.com',
notes: 'Scraped from box XX',
address: '184.168.221.28',
_id: 5565c77d8533c30967b5b279 ,
 name: 'alle',
source: 'Forbes.com',
notes: 'Scraped from box XX',
address: '82.118.66.19',
_id: 5565c77d8533c30967b5b27a ...
]

即使我在插入时将 forceServerObjectId 设置为 false,mongodb 也会在缓冲区数组中设置 _id。有可能防止这种情况吗? 我怎样才能确定清除缓冲区变量?

我猜问题是缓冲区仍然包含已经插入的数据,mongo 给出错误,因为数据库中已经存在相同的 ID(但我不确定我 100% 正确)

感谢回复

【问题讨论】:

【参考方案1】:

只有当数据库中存在包含一些_id 的文档(例如ID1)并且您尝试插入一个新文档时,该错误才会发生,该文档将ID1 作为其_id 字段的值。

这可能是由于以下原因:

您的集合中已经有一些文档,并且集合中有一个文档和 CSV 文件共享相同的_id CSV 文件中至少有两行共享相同的_id

如果_id 字段的值对您来说并不重要,您可以使用delete 直接在javascript 代码中从从CSV 读取的对象中删除该属性。

否则,您会遇到冲突,需要决定要如何处理重复的 _id 文档。如果您同意覆盖,您可以通过使用upsert: 1 选项来实现这一点,如果存在具有相同_id 的文档,它将使用新值更新文档。

【讨论】:

正如您从上面的代码中看到的 - 我没有将 _id 推入缓冲区,并且 csv 没有 _id 字段。 _Id 第一次执行 insertMany 后出现在缓冲区中。【参考方案2】:

修复了缓冲区的闭包:

 if(buffer.length >= 100 || readAllLines) 
    (function(buffer) 
       db.collection('peoples').insert(buffer, ... 
    )
    buffer = []
 

但仍在寻找解决方案 - 如何在插入时不更新缓冲区

【讨论】:

以上是关于Nodejs,mongodb在插入许多后更新数组的主要内容,如果未能解决你的问题,请参考以下文章

在嵌套数组 mongodb nodejs 中插入对象

如何使用 mongoose 和 NodeJs 在 Mongodb 的数组字段中插入数据

Go调用mongodb 更新数据不存在插入,存在就更新

如何更新数组NodeJS,MongoDB中的特定对象

MongoDB - 如何在数组中更新或插入对象

MongoDB 嵌套对象数组后查询