我们有一个订单系统,每个订单都有一个id。出于会计目的,我们需要一种方法来生成具有递增数字的发票。不使用sql数据库的最佳方法是什么? 我们正在使用node来实现该应用程序。
答案 0 :(得分:3)
http://www.mongodb.org/display/DOCS/How+to+Make+an+Auto+Incrementing+Field
第一种方法是将计数器保存在旁边文档中:
可以在一个侧面文档中保留当前_id的计数器 专柜专柜。然后原子地使用FindAndModify 获得一个id并增加计数器。
另一种方法是通过继续并递增碰撞边缘情况的id来乐观地循环并处理11000的双密钥错误代码。除非有高并发性写入特定集合,否则这种方法很有效。
人们可以用乐观的并发来做到这一点"如果不存在则插入" 循环。
但请注意该页面上的警告:
通常在MongoDB中,不会使用自动增量模式 _id(或其他字段),因为这在大型数据库集群上不能很好地扩展。相反,通常使用对象ID。
需要考虑的其他事项:
答案 1 :(得分:0)
我没有找到任何可行的解决方案,所以我在node.js中实现了“乐观循环”以获得自动递增的整数ID字段。使用异步模块实现while循环。
// Insert the document to the targetCollection. Use auto-incremented integer IDs instead of UIDs.
function insertDocument(targetCollection, document, callback) {
var keepRunning = true;
var seq = 1;
// $type 16/18: Integer Values
var isNumericQuery = {$or : [{"_id" : { $type : 16 }}, {"_id" : { $type : 18 }}]};
async.whilst(testFunction, mainFunction, afterFinishFunction);
// Called before each execution of mainFunction(). Works like the stop criteria of a while function.
function testFunction() {
return keepRunning;
}
// Called each time the testFunction() passes. It is passed a function (next) which must be called after it has completed.
function mainFunction(next) {
findCursor(targetCollection, findCursorCallback, isNumericQuery, { _id: 1 });
function findCursorCallback(cursor) {
cursor.sort( { _id: -1 } ).limit(1);
cursor.each(cursorEachCallback);
}
function cursorEachCallback(err, doc) {
if (err) console.error("ERROR: " + err);
if (doc != null) {
seq = doc._id + 1;
document._id = seq;
targetCollection.insert(document, insertCallback);
}
if (seq === 1) {
document._id = 1;
targetCollection.insert(document, insertCallback);
}
}
function insertCallback(err, result) {
if (err) {
console.dir(err);
}
else {
keepRunning = false;
}
next();
}
}
// Called once after the testFunction() fails and the loop has ended.
function afterFinishFunction(err) {
callback(err, null);
}
}
// Call find() with optional query and projection criteria and return the cursor object.
function findCursor(collection, callback, optQueryObject, optProjectionObject) {
if (optProjectionObject === undefined) {
optProjectionObject = {};
}
var cursor = collection.find(optQueryObject, optProjectionObject);
callback(cursor);
}
使用
进行通话 insertDocument(db.collection(collectionName), documentToSave, function() {if(err) console.error(err);});