2012-09-10 16 views
0

我們有一個訂單系統,每個訂單都有一個id。出於會計目的,我們需要一種方法來生成數量增加的發票。不使用sql數據庫的最佳方法是什麼? 我們使用節點來實現應用程序。用mongoDB創建遞增數字

+0

附答案 - 在這裏,你最終真正感興趣。傳統上我使用SQL,但也實現了mongo ... – bryanmac

回答

3

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

第一種方法是保持櫃檯邊文檔中:

人們可以保留當前_id的櫃檯邊文檔中,在 收集專用於計數器。然後使用FindAndModify以原子方式獲取一個id並遞增計數器。

另一種方法是樂觀地循環並通過繼續並增加碰撞邊緣情況下的id來處理11000的dup密鑰錯誤代碼。除非寫入特定集合的併發性很高,否則這種方式很有效。

一個可以做到樂觀併發「插入如果不存在」 循環。

但要注意,頁面上的警告:

一般在MongoDB中,一個不使用 _id的(或其他字段)的自動遞增的模式,因爲這不能按比例增長以及大型數據庫羣集。而是通常使用對象ID。

其他需要考慮的事情:

  • Timestamp - 獨特的長但不增加(上劃時代基地)
  • 混合方法 - 應用程序不一定要挑一個存儲選項。
  • 根據客戶,日期/時間等部件等,爲您生成並處理衝突,提出您的ID機制。取決於方案,碰撞可能性要小得多。不一定增加,但是是獨特的,並且具有明確定義的可讀模式。
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);});