因此文档推荐.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,所以只需增加你想要的数量。