MongoDB 如何實現自動增長 ID

創建 MongoDB 文檔時,如果沒有賦值 ID,系統會自動幫你創建一個,通常會在客戶端由驅動程序完成。得到的 ObjectId 類似於這種。ObjectId 使用 12 字節的存儲空間,每個字節兩位十六進制數字,是一個 24 位的字符串。其含義分別代表時間戳、機器碼、PID、計數器。時間戳是文檔創建時的時間,只是從十進制轉化成了十六進制。機器碼是生成文檔主機的 ID,爲了區分多主機而生成的。PID 則是區分同主機下不同 mongoDB 進程產生的,同樣防止衝突。前面的 9 個字節是保證了一秒內不同機器不同進程生成 ObjectId 不衝突,最後的 3 個字節是一個自動增加的計數器,用來確保在同一秒內產生的 ObjectId 也不會衝突,允許 256 的 3 次方等於 16777216 條記錄的唯一性。

顯然系統生成的 ObjectID 已經很嚴謹了,但是在選擇系統創建還是程序創建 id 上,經過網上查找的一些資料,得到的結論是儘量採用程序創建的方式,速度、可讀性、可維護性都要強於系統創建。

MongoDB 沒有像 SQL 一樣有自動增長的功能, MongoDB 的 _id 是系統自動生成的 12 字節唯一標識。但在某些情況下,我們可能需要實現 ObjectId 自動增長功能。由於 MongoDB 沒有實現這個功能,我們可以通過編程的方式來實現,以下我們將在 counters 集合中實現_id 字段自動增長。

使用 counters 集合

考慮以下 products 文檔。我們希望 _id 字段實現 從 1,2,3,4 到 n 的自動增長功能。

{
  "_id":1,
  "product_name""Apple iPhone",
  "category""mobiles"
}

爲此,創建 counters 集合,序列字段值可以實現自動長:

>db.createCollection("counters")

現在我們向 counters 集合中插入以下文檔,使用 productid 作爲 key:

{
  "_id":"productid",
  "sequence_value"0
}

sequence_value 字段是序列通過自動增長後的一個值。

使用以下命令插入 counters 集合的序列文檔中:

>db.counters.insert({_id:"productid",sequence_value:0})

創建 Javascript 函數

現在,我們創建函數 getNextSequenceValue 來作爲序列名的輸入, 指定的序列會自動增長 1 並返回最新序列值。在本文的實例中序列名爲 productid 。

>function getNextSequenceValue(sequenceName){
   var sequenceDocument = db.counters.findAndModify(
      {
         query:{_id: sequenceName },
         update: {$inc:{sequence_value:1}},
         "new":true
      });
   return sequenceDocument.sequence_value;
}

使用 Javascript 函數

接下來我們將使用 getNextSequenceValue 函數創建一個新的文檔, 並設置文檔 _id 自動爲返回的序列值:

>db.products.insert({
   "_id":getNextSequenceValue("productid"),
   "product_name":"Apple iPhone",
   "category":"mobiles"})

>db.products.insert({
   "_id":getNextSequenceValue("productid"),
   "product_name":"Samsung S3",
   "category":"mobiles"})

就如你所看到的,我們使用 getNextSequenceValue 函數來設置 _id 字段。

爲了驗證函數是否有效,我們可以使用以下命令讀取文檔:

>db.products.find()

以上命令將返回以下結果,我們發現 _id 字段是自增長的:

{ "_id" : 1, "product_name" : "Apple iPhone""category" : "mobiles"}

{ "_id" : 2, "product_name" : "Samsung S3""category" : "mobiles" }
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/R607DJoPxzf1Y3zJSYM0iA