[英]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.