我正在查看有关MongoDb中自动递增字段的文章。 http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/
这在理论上似乎很好,但在我的应用程序中并不起作用,因为所有数据库调用都是异步的。 Ps,Im使用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.
});
这对于一个文档可以正常工作,但是如果我进行批量插入(传递要插入的多个文档的数组),我无法看到它是如何工作的。我需要批量插入。
回到循环和单个插入似乎不是一个好的解决方案。
你有什么好的解决方案吗?
答案 0 :(得分:1)
因此,文档建议.findAndModify()
用于此类操作,因为"更新/递增"的操作并检索结果是" atomic"操作。当然,如果你一次要插入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 ) );
}
);
});
嗯,这是基本的模拟器,但你应该明白这个想法。基本上只是抓住一大堆价值&#34;您打算插入多少条目并使用每个&#34;值&#34;在插入实际文档时。
最糟糕的情况?插入在某处失败,并非所有值都在文档中结束。所以呢?没关系,因为关键是你已经增加了计数器,没有其他过程可以抓住那些相同的值#34;从柜台。
正如您可以从评论中收集到的,这是我试图引导您的地方,您可能已经完成了基础知识。没有什么可以说你不能将那个计数器增加1以上,所以只需增加你想要的数量。