MongoDB中ObjectId生成規則參考

MongoDB中我們經常會接觸到一個自動生成的字段:”_id”,類型爲ObjectId。本文會詳解ObjectId的構成和使用。

ObjectId構成

之前我們使用MySQL等關係型數據庫時,主鍵都是設置成自增的。但在分佈式環境下,這種方法就不可行了,會產生衝突。爲此,MongoDB採用了一個稱之爲ObjectId的類型來做主鍵。ObjectId是一個12字節的 BSON 類型字符串。按照字節順序,一次代表:

4字節:UNIX時間戳
3字節:表示運行MongoDB的機器
2字節:表示生成此_id的進程
3字節:由一個隨機數開始的計數器生成的值
ObjectId獲取時間

從ObjectId的構造上來看,內部就嵌入了時間類型。我們肯定可以從中獲取時間信息:即插入此文檔時的時間。MongoDB對ObjectId對象提供了getTimestamp()方法來獲取ObjectId的時間。

a = new ObjectId()
ObjectId(“53102b43bf1044ed8b0ba36b”)
a.getTimestamp()
ISODate(“2014-02-28T06:22:59Z”)
根據時間構造ObjectId

上例是直接使用MongoDB提供的新建方法來構造ObjectId的,我們自己可不可以通過字符串來構造呢?看下例:

// 使用Date的字符串構造方法生成日期
// 然後使用Date對象的getTime獲取毫秒數,再除以1000得到標準時間戳

a = new Date(“2012-12-12 00:00:00”).getTime()/1000
1355241600
// 獲取時間戳的標準十六進制表示
a = a.toString(16)
50c75880

// 在後面填補16個0

a = a + new Array(17).join(“0”)
50c758800000000000000000

// 使用24個字符串構造ObjectId

b = new ObjectId(a)
ObjectId(“50c758800000000000000000”)

// 獲取時間以驗證

b.getTimestamp()
ISODate(“2012-12-11T16:00:00Z”)
上述過程中 new Array(17).join(“0″)目的是生成16個0拼接的字符串。

這裏使用了點小技巧。new Array(17)構造了一個17個元素的數組,但是數組裏面沒有元素,join(atr)方法的作用是連接數組元素並且以其參數分割。17個元素正好有16個間隔,所以最終拼接起來的字符串爲16個。

根據ObjectId按照插入時間排序

MongoDB默認在ObjectId上建立索引,是按照插入時間排序的。我們可以使用此索引進行查詢和排序。

// 按序插入三個文檔

db.col.insert({“num”:1})
db.col.insert({“num”:2})
db.col.insert({“num”:3})
db.col.find().pretty()
{ “_id” : ObjectId(“53102fb4bf1044ed8b0ba36c”), “num” : 1 }
{ “_id” : ObjectId(“53102fb9bf1044ed8b0ba36d”), “num” : 2 }
{ “_id” : ObjectId(“53102fbabf1044ed8b0ba36e”), “num” : 3 }

// 按照_id升序,即按照插入時間升序

db.col.find().sort({“_id”:1}).pretty()
{ “_id” : ObjectId(“53102fb4bf1044ed8b0ba36c”), “num” : 1 }
{ “_id” : ObjectId(“53102fb9bf1044ed8b0ba36d”), “num” : 2 }
{ “_id” : ObjectId(“53102fbabf1044ed8b0ba36e”), “num” : 3 }

// 按照_id降序,即按照插入時間降序

db.col.find().sort({“_id”:-1}).pretty()
{ “_id” : ObjectId(“53102fbabf1044ed8b0ba36e”), “num” : 3 }
{ “_id” : ObjectId(“53102fb9bf1044ed8b0ba36d”), “num” : 2 }
{ “_id” : ObjectId(“53102fb4bf1044ed8b0ba36c”), “num” : 1 }

// 抽取num = 2的ObjectId用來過濾

num2 = ObjectId(“53102fb9bf1044ed8b0ba36d”)
ObjectId(“53102fb9bf1044ed8b0ba36d”)

// 找出插入時間在num2之後的數據

db.col.find({ “_id”:{$gt:num2}}).pretty()
{ “_id” : ObjectId(“53102fbabf1044ed8b0ba36e”), “num” : 3 }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章