2021 iThome 鐵人賽 - DAY5 資料型別與 _id

2021 iThome 鐵人賽 MongoDB披荊斬棘之路


DAY5 資料型別與 _id

資料型別

首先要理解 MongoDB 儲存的格式 BSON,就是 Binary JSON,雖然呈現都是 JSON 格式,但儲存還是有型別之分,這就是 BSON 的優點。

BSON 型別有以下幾種,常見的就不特別說明了

  • int
  • long
  • string
  • double
  • decimal
  • bool
  • date
  • timestamp
  • array
  • null
  • binData:此欄位儲存二進制的資料(binary data)
  • objectId:MongoDB 的精髓,稍後會提到
  • object:相當於 embedded documentnested document,更白話的說就是文件內的子文件,如範例的 publisher 欄位:
1
2
3
4
5
6
7
8
9
10
{
"_id": ObjectId("612cf44a031915cb2af17374"),
"name":"Barcraft",
"publisher":
{
"companyName":"Clizzard",
"country":"Taiwan",
"city":"Taipei"
}
}
  • regex: 這型別是宣告此欄位專門用來儲存正則式
1
2
3
4
{
"_id": ObjectId("612cf44a031915cb2af17374"),
"regexField": /[1-5]/
}
  • javascript:儲存 javascript 語法用
1
2
3
4
{
"_id": ObjectId("612cf44a031915cb2af17374"),
"jsCode": "function() {var a = 1;}"
}

資料型別有很多,不過使用上多半還是原始的那幾種,比較多人討論到的是時間型別

Date我本身還真的沒使用過,大部分都是使用Timestamp就能解決,且還有時區問題,如果沒開發過跨時區系統,請務必縝密思考使用情境,例如不同時區的使用者如何查詢資料。

_id 是什麼

  • MongoDB 預設每一個文件都有的欄位(連 embedded document 也是)
  • 系統會自動產生這個欄位
  • 每一個文件的唯一位置
  • 系統預設的 single index key
  • Collection 層級的唯一值
  • 資料型別為 ObjectId

長相如下:
_id: ObjectId("612cf44a031915cb2af17374")

_id 是由16進位、24字元所組成的(請特別注意並不等於 string),故 ObjectId 為 12 bytes,這 12 bytes 組成依序為:

  1. Timestamps 的 4 bytes
  2. 隨機碼的 5 bytes。
  3. 隨機起始的遞增計數器 3 bytes

特別要注意的是 timestamp 精確度只到秒級;第二項的隨機碼又可拆分為

  • 機器碼(machine id) 3 bytes
  • 作業序(process id) 2 bytes

*註:這個項目在 MongoDB document 已經移除細節討論,不過還是可以從過往文章來了解


所以最常被提及到的是,「系統產生的 _id 是否會重複?」關於這個答案其實可以從拆分的這 12 bytes 得到答案,在非刻意的情況下,理論上是有可能重複的。假設一秒內一台機器的同一個process,產生超過 3bytes 的計數器數量,就有可能會重複了。但在大部分商務情境使用,應該是沒什麼機會遇到

_id 可否自行定義?

可以,只要你確保 Collection 層級的唯一性。

假設這是一個會員 Collection,那通常 MemberId 就相當適合當作 _id 欄位,因為 MemberId 是不會重複的,且可以快速地找到這筆資料,是上上之選。

_id 一定要 ObjectId 型別?

其實上面的問題就給出答案了,不需要。
int, long 都可以當作是 _id 的型別,只是 MongoDB 幫你產生的是 ObjectId。

  • 作者: MingYi Chou
  • 版權聲明: 轉載不用問,但請註明出處!本網誌均採用 BY-NC-SA 許可協議。