【问题标题】:Correct way to insert many records into Mongodb with Node.js使用 Node.js 将许多记录插入 Mongodb 的正确方法
【发布时间】:2015-12-30 13:19:18
【问题描述】:

我想知道使用 Node.js 向 Mongodb(尽管可以是任何其他数据库)进行批量插入的正确方法是什么

我已经编写了以下代码作为示例,尽管我相信它是错误的,因为 db.close() 可能在所有异步 collection.insert 调用完成之前运行。

MongoClient.connect('mongodb://127.0.0.1:27017/test', function (err, db) {
    var i, collection;
    if (err) {
        throw err;
    }
    collection = db.collection('entries');
    for (i = 0; i < entries.length; i++) {
        collection.insert(entries[i].entry);
    }
    db.close();
});

【问题讨论】:

    标签: javascript node.js mongodb


    【解决方案1】:

    如果您的 MongoDB 服务器是 2.6 或更高版本,最好利用写入命令 Bulk API 来执行批量插入操作,这些操作只是在服务器可以轻松构建批量操作,从而通过对大型集合的更新获得性能提升。

    批量发送批量插入操作会减少到服务器的流量,因此不会在单独的语句中发送所有内容,而是分解成可管理的块以供服务器提交,从而执行高效的电汇交易。使用这种方法等待回调中响应的时间也更少。

    这些批量操作主要有两种形式:

    • 有序批量操作。这些操作按顺序执行所有操作,并在第一次写入错误时出错。
    • 无序批量操作。这些操作并行执行所有操作并聚合所有错误。无序批量操作不保证执行顺序。

    注意,对于早于 2.6 的旧服务器,API 将下转换操作。但是,不可能进行 100% 的下转换,因此可能存在一些无法正确报告正确数字的极端情况。

    在您的情况下,您可以像这样以 1000 个批量实现批量 API 插入操作:

    对于 MongoDB 3.2+,使用 bulkWrite

    var MongoClient = require('mongodb').MongoClient;
    var url = 'mongodb://localhost:27017/test';
    var entries = [ ... ] // a huge array containing the entry objects
    
    var createNewEntries = function(db, entries, callback) {
    
        // Get the collection and bulk api artefacts
        var collection = db.collection('entries'),          
            bulkUpdateOps = [];    
    
        entries.forEach(function(doc) {
            bulkUpdateOps.push({ "insertOne": { "document": doc } });
    
            if (bulkUpdateOps.length === 1000) {
                collection.bulkWrite(bulkUpdateOps).then(function(r) {
                    // do something with result
                });
                bulkUpdateOps = [];
            }
        })
    
        if (bulkUpdateOps.length > 0) {
            collection.bulkWrite(bulkUpdateOps).then(function(r) {
                // do something with result
            });
        }
    };
    

    对于 MongoDB

    var MongoClient = require('mongodb').MongoClient;
    var url = 'mongodb://localhost:27017/test';
    var entries = [ ... ] // a huge array containing the entry objects
    
    var createNewEntries = function(db, entries, callback) {
    
        // Get the collection and bulk api artefacts
        var collection = db.collection('entries'),          
            bulk = collection.initializeOrderedBulkOp(), // Initialize the Ordered Batch
            counter = 0;    
    
        // Execute the forEach method, triggers for each entry in the array
        entries.forEach(function(obj) {         
    
            bulk.insert(obj);           
            counter++;
    
            if (counter % 1000 == 0 ) {
                // Execute the operation
                bulk.execute(function(err, result) {  
                    // re-initialise batch operation           
                    bulk = collection.initializeOrderedBulkOp();
                    callback();
                });
            }
        });             
    
        if (counter % 1000 != 0 ){
            bulk.execute(function(err, result) {
                // do something with result 
                callback();             
            }); 
        } 
    };
    

    调用createNewEntries()函数。

    MongoClient.connect(url, function(err, db) {
        createNewEntries(db, entries, function() {
            db.close();
        });
    });
    

    【讨论】:

    • 如果counter % 1000 == 0,你将如何关闭数据库
    • 您可能必须在if (counter % 1000 != 0 ){ ... } 语句块之后添加db.close(); 语句才能关闭数据库。
    • 当来自 forEach 的 bulk.execute 调用仍在运行时,您不会冒险调用 db.close() 吗?
    • 你不会因为这里bulk.execute()是一个mongodb写操作,它是一个异步IO调用。这允许 node.js 在bulk.execute() 完成其数据库写入和回调之前继续进行事件循环。我已经用这种回调方法更新了我的答案。
    • 这样方便多了,而且效果很好!感谢您的回答。
    【解决方案2】:

    您可以使用insertMany。它接受一个对象数组。检查API

    【讨论】:

    • 如果您要插入少量记录,那没关系,但如果您有数千条记录呢?
    • 在批量操作中,mongoDB(3.x) 在单个组中批量处理 1000 个文档,对于更多文档,它会创建组并执行它。请参考docs.mongodb.com/v3.2/reference/method/db.collection.insertMany/…
    • documentation 中的另一个位置,其中重复了先前关于 insertMany 的评论:PyMongo 将根据接受的最大消息大小自动将批次拆分为较小的子批次MongoDB,支持非常大的批量插入操作。
    【解决方案3】:

    3.2 版中的新功能。

    db.collection.bulkWrite() 方法提供了执行批量插入、更新和删除操作的能力。 MongoDB 还支持通过db.collection.insertMany() 进行批量插入。

    bulkWrite 仅支持 insertOne、updateOne、updateMany、replaceOne、deleteOne、deleteMany

    在您使用单行代码插入数据的情况下,可以使用 insertMany 选项。

     MongoClient.connect('mongodb://127.0.0.1:27017/test', function (err, db) {
                var i, collection;
                if (err) {
                    throw err;
                }
                collection = db.collection('entries');
                collection.insertMany(entries)
                db.close();
            });

    【讨论】:

      【解决方案4】:
      var MongoClient = require('mongodb').MongoClient;
      var url = 'mongodb://localhost:27017/test';
      var data1={
          name:'Data1',
          work:'student',
          No:4355453,
          Date_of_birth:new Date(1996,10,17)
      };
      
      var data2={
          name:'Data2',
          work:'student',
          No:4355453,
          Date_of_birth:new Date(1996,10,17)
      };
      
      MongoClient.connect(url, function(err, db) {
          if(err!=null){
              return console.log(err.message)
          }
      
          //insertOne
          db.collection("App").insertOne(data1,function (err,data) {
      
              if(err!=null){
                  return console.log(err);
              }
              console.log(data.ops[0]);
          });
      
          //insertMany
      
      var Data=[data1,data2];
      
      db.collection("App").insertMany(Data,forceServerObjectId=true,function (err,data) {
      
              if(err!=null){
                  return console.log(err);
              }
              console.log(data.ops);
          });
          db.close();
      });
      

      【讨论】:

      • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
      • 此代码仅用于插入多条记录或单条记录示例
      • "forceServerObjectId=true" 适用于重复键错误 id,谢谢
      猜你喜欢
      • 2016-12-09
      • 1970-01-01
      • 2015-01-08
      • 2011-07-05
      • 1970-01-01
      • 1970-01-01
      • 2014-04-24
      • 1970-01-01
      相关资源
      最近更新 更多