0

我们有一个订单系统,其中每个订单都有一个 ID。出于会计目的,我们需要一种方法来生成具有递增数字的发票。不使用 sql 数据库的最佳方法是什么?我们正在使用节点来实现应用程序。

4

2 回答 2

3

http://www.mongodb.org/display/DOCS/How+to+Make+an+Auto+Incrementing+Field

第一种方法是将计数器保存在辅助文档中:

可以将当前 _id 的计数器保存在边文档中,在专用于计数器的集合中。然后使用 FindAndModify 原子地获取一个 id 并递增计数器。

另一种方法是乐观地循环并通过继续并增加碰撞边缘情况的 id 来处理 11000 的 dup key 错误代码。除非对特定集合进行高并发写入,否则效果很好。

可以通过乐观并发“如果不存在则插入”循环来做到这一点。

但请注意该页面上的警告:

通常在 MongoDB 中,不会对 _id(或其他字段)使用自动增量模式,因为这在大型数据库集群上不能很好地扩展。相反,通常使用对象 ID。

其他需要考虑的事项:

  • 时间戳- 唯一长但不递增(基于纪元)
  • 混合方法 - 应用程序不一定要选择一种存储选项。
  • 根据您生成和处理冲突的客户、日期/时间部分等内容提出您的 id 机制。根据方案,冲突的可能性要小得多。不一定是递增的,但它是唯一的,并且具有明确定义的可读模式。
于 2012-09-10T11:40:10.033 回答
0

我没有找到任何可行的解决方案,所以我在 node.js 中实现了“乐观循环”来获取自动递增的整数 ID 字段。使用 async 模块实现 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);});

于 2015-06-04T20:04:00.987 回答