2015-04-12 60 views
0

我有一個「部門」的MongoDB集合,每個部門都有一個「門票」的子集合。在舊的基於MySQL的系統中,我們通過對現有記錄進行計數並添加一個記錄,爲每張票(每個部門)分配一個編號。按序編號的MongoDB子文檔

這給每個部門一個人類可讀編號系統來識別門票:1,2,3,等

然而,在蒙戈,這樣的自動遞增字段中未使用,我發現,因爲操作可能是異步的(在NodeJS應用程序中使用Mongoose),對現有記錄進行計數可能不可信(與增加部門集合中的計數器相同)

我花費時間尋找解決方案,但是發現它很困難整理不相關的主題。

是否有任何可靠的方法來創建依賴於自定義查詢的序列號系統?

這裏的模型的例子/保存代碼,我與

var OrganizationSchema = new Schema({ 
    name: { 
     type: String, 
     required: true 
    }, 
    departments: [Department.schema] 
}); 
var DepartmentSchema = new Schema({ 
    name: { 
     type: String, 
     required: true 
    } 
}); 

// Tickets aren't stored as subdocuments in Departments because there could be 
// a lot, I didn't want it to affect performance 
var TicketSchema = new Schema({ 
    project: { 
     type: [{ type: Schema.Types.ObjectId, ref: 'Department' }], 
     required: true 
    }, 
    summary: { 
     type: String, 
     required: true 
    } 
}); 


// in-progress save code 
Organization.findOne({ 'departments._id': department }, function(err, org){ 

    var lastTicketId = org.departments[0].lastTicketId; 
    console.log(lastTicketId); 

    var ticket = new Ticket({ 
     department: department, 
     summary: req.body.summary 
    }); 

    ticket.save(function(err, result) { 

     if (err) { 
      return next(err); 
     } 

     Organization.findOneAndUpdate(
      { 'departments._id': department }, 
      { $inc: { 'departments.$.lastTicketId': 1 } }, 
      function(err, result) { 
       console.log('saving ' + result.departments[0].lastTicketId); 
      } 
     ); 
    }); 
}); 

玩弄這節省代碼是一個API端點,所以我從for環批量測試20-一些API請求。這意味着他們進入非常快,我可以真正看到編號的異步效應。

的的console.log輸出是:

loading 0 
loading 0 
saving 0 
loading 1 
loading 1 
loading 1 
loading 1 
loading 1 
loading 1 
loading 1 
saving 1 
saving 2 
loading 1 
loading 1 
loading 1 
loading 1 
loading 1 
loading 1 
loading 1 
loading 1 
loading 1 
loading 1 
loading 1 
loading 1 
loading 1 
loading 1 
loading 1 
loading 1 
loading 1 
loading 1 
saving 3 
saving 4 
saving 9 
saving 5 
saving 10 
saving 6 
saving 11 
saving 7 
saving 12 
saving 17 
saving 8 
saving 13 
saving 18 
saving 23 
saving 14 
saving 19 
saving 24 
saving 15 
saving 20 
saving 25 
saving 16 
saving 21 
saving 22 
+0

如果您使用的是Mongoose,則每個子文檔會自動獲得一個'_id'。您也可以從ID中獲取創建日期,以便告訴您創建的順序,如果這是您想要的。 –

+0

我意識到每個subdoc都有一個ObjectID,但是這個編號系統是針對人而不是代碼的。我會在內部總是依賴_id,但是當人們與應用程序交互時,他們不會想要基於它們來引用門票 - 他們需要一個令人難忘的數字,並且可以通過鍵入。 – helion3

+0

我總覺得你的建模有問題。你能展示一些你的數據的例子嗎? –

回答

0

最後,這個問題有點不正確,因爲我認爲孟戈是個問題。但是,在回顧我發佈的日誌時,我意識到最終這些數字正在遞增,所以我的問題必須是JavaScript問題。

我想到查詢最後一個ID,然後保存票證,然後更新最後一個ID的效率太低,但必須讓異步查詢的空間重疊。

我決定重寫保存邏輯來驗證票證而不保存它,然後在單個查詢中遞增最後一個ID,然後用適當的值保存問題。

到目前爲止它看起來很完美。

// Ensure validation passes before we increment an ID 
// so we avoid disconnected IDs if it fails later 
ticket.validate(function(err) { 
    if (err) { 
     return next(err); 
    } 

    // Find and update last ID in one transaction 
    // due to async issues 
    Organization.findOneAndUpdate(
     { 'departments._id': department }, 
     { $inc: { 'departments.$.lastTicketId': 1 } }, 
     function(err, result) { 
      if (err) { 
       return next(err); 
      } 

      ticket.displayId = result.departments[0].lastTicketId; 
      ticket.save(function(err, user) { 
       if (err) { 
        return next(err); 
       } 
       // success 
      }); 
     } 
    ); 
}); 
0

存在與MongoDB的

  1. 一個計數器收集
  2. 樂觀環2個可能的技術

see mongoDB article here:

這篇文章中沒有提到的東西是計數器的集合保證了多進程環境中唯一的遞增ID,但是如果這個ID用於插入插入順序不是100%保證對應於這個ID。 如果插入順序是關鍵用途樂觀環技術

0

如果你使用的貓鼬,你可以嘗試自動遞增:https://www.npmjs.com/package/mongoose-auto-increment每次

var OrganizationSchema = new mongoose.Schema({ 
    ... 
}); 
var DepartmentSchema = new mongoose.Schema({ 
    ... 
}); 

var TicketSchema = new Schema({ 
    ticketNumber: { type: Number, required: true }, 
    project: { 
     type: [{ type: Schema.Types.ObjectId, ref: 'Department' }], 
     required: true}], 
    ... 
}); 

TicketSchema.plugin(autoIncrement.plugin, {model: 'Ticket', field: 'ticketNumber'}); 

這將自動遞增的ticketNumber你插入一張票文檔。它不是每個部門增加 - 只是每票的唯一編號。

最新的門票號碼存儲在MongoDB mongoose-auto-increments的特殊文檔集合中,因此,即使您處於Web養成的多服務器情況下,也不會在選擇下一個數字時出現問題。

但是,如果手動插入票據文檔,請小心。您也需要手動更新mongoose-auto-increments集合。