2021 iThome 鐵人賽 - DAY13 MongoDB 索引(Index) 種類與建立方式

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


DAY13 MongoDB 索引(Index) 種類與建立方式

什麼是索引(Index)

索引是資料庫設計中非常重要的一環,透過針對特定欄位(一個以上)建立索引,使得任何操作能夠快速找到資料,這也是為什麼操作的查詢條件通常都須建立索引的緣故,所以使用者情境(user scenario)對開發者來說非常重要,如果沒有這些情境,開發者無法預測這個功能該如何使用,進而無法設計出合適的結構或者索引等。

預設索引

MongoDB 內的所有 collection 都有一個 Default Index,打開任一文件都會看到一個 _id 欄位,就是這個。

_id 不需要指定,寫入資料庫時就會自動幫你產生,當然你也可以自己客製化,在某些情境很適合。

索引值排序

MongoDB 索引欄位是有排序的,預設是正序1,反序-1則需要特別設定,至於要使用哪一種排序,需要根據你的使用情境來決定。

通常,跟時間相關都會查詢與現在較近的為主,例如最近一個月的營收、這週的進貨表等等,這樣就很適合使用反序來建立索引。

索引命名

官方的文件載明,建議命名為 [欄位名稱1]_[排序]_[欄位名稱2]_[排序] 這樣的方式。
例如現在有兩個欄位分別叫 ProductId 使用正序,CreateTime 使用倒序,那以此建立的 index 會命名為ProductId_1_CreateTime_-1

  • 索引命名長度為 127 bytes

索引種類與建立

單一欄位索引

顧名思義,使用一個欄位建立的 Index。

以下範例皆使用此 employee 的 collection (僅範例使用,沒考慮設計上問題)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
"_id": ObjectId("60a7755055caee86c7479c96"),
"name": "Aaron",
"age": 30,
"department": 1,
"startWork": 2021-05-21T00:00:00.000+0800
"address": {
"city": "taipei",
"district": "east"
},
"assets": [
{"sn": "PC001", "name":"personal computer"},
{"sn": "OD001", "name": "office desk"}
]
},
{
"_id": ObjectId("60a7756955caee86c7479c97"),
"name": "Brad",
"age": 32,
"department": 2,
"startWork": 2021-04-21T00:00:00.000+0800,
"address": {
"city": "hsinchu",
"district": "south"
},
"assets": [
{"sn": "PC002", "name":"personal computer"},
{"sn": "OD002", "name": "office desk"}
]
}

單一欄位建立索引

針對 department 欄位建立索引:

1
db.employee.createIndex({"department": 1})

巢狀文件欄位索引

Index 也可以建立在 embedded field 上,使用 . 來做階層索引。以 city 為例:

1
db.employee.createIndex({"address.city": 1})

複合欄位索引

顧名思義是使用兩個以上的欄位組成的索引,在大部分情況都是使用這個的。以上面的範本為例:

1
db.employee.createIndex({"startWork": -1, "department" : 1})

Multikey欄位索引

Multikey index 是針對欄位是 array 使用的,使用方式如同一般 index 一樣,不需要額外指定它是 multikey。

1
db.employee.createIndex({"assets.sn" : 1})

文字索引

文字索引,建立一個以上欄位的文字查詢索引。要特別注意的是一個collection只能有一個文字索引

例如要針對 name 欄位建立文字索引,語法稍微不同,如下:

  • Create
1
db.employee.createIndex({"name" : "text"})
  • Query

查詢時不需指定欄位,需使用 $text $search 語法。

單一字查詢:

1
db.employee.find({$text : {$search: "aaron"}}})

查詢多個字直接空白隔開即可,例如我要查詢包含 aaron asgard 的名字:

1
db.employee.find({$text : {$search: "aaron asgard"}}})

查詢包含空格的完整字串:

1
db.employee.find({$text : {$search: \""aaron asgard\""}}})

還有個反向的功能,例如要排除某一個字,可以使用 - 符號:
搜尋 aaron 但不包含 asgard

1
db.employee.find({$text : {$search: "aaron -asgard"}}})

取得索引

看完後才發現忘記講如何取得索引,趕緊補上。

1
db.employee.getIndexes()

刪除索引

1
db.employee.dropIndex({"index_name"})

索引種類大致上介紹到這邊,明天繼續更深入的內容!

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