簡體   English   中英

具有異步批量插入功能的MongoDb中的自動增量字段

[英]Auto-increment field in MongoDb with async bulk insertion

我正在看有關MongoDb中自動遞增字段的文章。 http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/

從理論上講,這似乎不錯,但是在我的所有數據庫調用都不同步的應用程序中不起作用。 ps,即時通訊使用Mongoskin。 考慮一下:

var getNextSequence function (name) {
  db.counters.findAndModify({_id: 'invoiceNr'}, {}, {$inc: {seq: 1}}, {new: true}, function(err, doc) {
    if (err) {
      return next(err);
    }
    return doc.seq;
  });
}; 

var seq = getNextSequence('invoiceNr');
console.log(seq);

這個(Console.log)執行時當然沒有任何值...

這讓我想到了嵌套回調(經典的Node風格):

db.counters.findAndModify({_id: 'invoiceNr'}, {}, {$inc: {seq: 1}}, {new: true}, function(err, doc) {
  if (err) {
    return next(err);
  }
  var seq = getNextSequence('invoiceNr');
  // Do something with the seq, like using it when inserting another document.
});

這對於一個文檔來說可以很好地工作,但是如果我進行批量插入(傳遞要插入的多個文檔的數組),我看不到它將如何工作。 我需要大量插入。

回到循環和單次插入似乎不是一個好的解決方案。

您對此有什么好的解決方案?

因此,文檔建議對這種類型的操作使用.findAndModify() ,因為“更新/遞增”和獲取結果的操作是“原子”操作。 當然,如果您一次要插入500個文檔,則不希望返回“獲取下一個增量” 500次,因為那樣太瘋狂了。 但是您缺少這個概念。

誰說您必須加1 簡而言之,當您知道要插入500個項目時,您只想將當前計數器增加501,這樣要求下一個計數器值的下一個操作將獲得已經增加501的值,因此該部分是好的。

現在,您要求將計數器增加500塊,您基本上就可以使用它們了。 因此,您知道要使用的第一個值基本上從您的返回值減去500開始,並且您想在實際返回的值上結束插入。

因此,您需要這樣的代碼:

var async = require('async'),
    mongo = require('mongoskin'),
    db = mongo.db('mongodb://localhost/test');


// The general incrementer

function getNextSequence( name, increment, callback ) {

  // Handling passing in "increment" as optional
  var args = Array.prototype.slice.call(arguments, 1);

  callback = args.pop();
  increment = args.length ? args.shift() || 1 : 1; // default 1

  db.collection('counters').findAndModify(
    { "_id": name },
    {},
    { "$inc": { "seq": increment } },
    { "new": true, "upsert": true },
    function(err,doc) {
      callback(err,doc.seq);
    }
  );

}

// Meat of your insertion logic

db.collection('target',function(err, collection) {

  var arrayToInsert = []; // simulating, but 500 items long assumed
  for (var x=0; x < 500; x++) {
    arrayToInsert.push({
      "x": x
    });
  }

  var bulk = collection.initializeOrderedBulkOp();

  async.waterfall(
    [
      function(callback) {
        getNextSequence('invoiceNo',arrayToInsert.length + 1,callback);
      },
      function(seq,callback) {
        var current = seq - arrayToInsert.length;
        var index = 0;

        async.whilst(
          function() { return index < arrayToInsert.length },
          function(callback) {
            doc = arrayToInsert[index];
            doc["invoice"] = current;
            bulk.insert( doc );
            index++;
            current++
            callback();
          },
          function(err) {
            bulk.execute(callback);
          }
        );
      }
    ],
    function(err,result) {
      if (err) throw err;
      // Log BulkWrite result
      console.log( JSON.stringify( result, undefined, 2 ) );
    }
  );

});

好吧,這是基本的模擬器,但是您應該明白這一點。 本質上,只需抓住一塊“值”即可確定要插入多少個條目,並在插入實際文檔時使用每個“值”。

最壞的情況是? 插入在某處失敗,並且並非所有值最終都出現在文檔中。 所以呢? 沒關系,因為關鍵是您已經增加了計數器,並且沒有其他進程可以從計數器中獲取那些相同的“值”。

從您的評論中可以看出,這就是我試圖引導您的地方,您可能已經掌握了基礎知識。 沒有什么可以說您不能將該計數器增加超過1,因此只需增加您想要的數量即可。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM