【MongoDB】多鍵索引(Multikey Indexes)

本章內容:

  • 創建多鍵索引
  • 指標界限
  • 唯一多鍵索引
  • 侷限性
  • 例子

如果一個字段的保存值是數組,那麼,爲該字段創建索引時,MongoDB爲數組中的每個元素創建一個索引鍵。這些多鍵索引支持對數組字段的有效查詢。可以在數組上構造多鍵索引,數組中既可以保存標量值[1](例如字符串,數字)也可以是嵌套文檔。

addr.zip字段上的多鍵索引圖。addr字段包含一個地址文檔數組。地址文檔包含”zip”字段。

 

[1]標量值是指既不是嵌入式文檔也不是數組的值。

一、創建多鍵索引

要創建多鍵索引,請使用db.collection.createIndex()方法:

db.coll.createIndex( { <field>: < 1 or -1 > } )

如果一個索引字段是數組,MongoDB會自動創建一個多鍵索引;而無需顯式指定多鍵類型。

在版本3.4中的更改:僅對於WiredTigerIn-Memory存儲引擎

從MongoDB 3.4開始,對於使用MongoDB 3.4或更高版本創建的多鍵索引,MongoDB會跟蹤創建了多鍵索引的一個或多個字段。跟蹤此信息使MongoDB查詢引擎可以使用更嚴格的索引範圍。

 

二、指標界限

如果索引是多鍵,則索引範圍的計算需遵循特殊規則。有關多鍵索引範圍的詳細信息,請參見多鍵索引範圍

 

三、唯一多鍵索引

對於唯一索引,唯一性約束作用跨越了集合中的多個獨立文檔,而不是單個文檔。

因爲唯一性約束適用於單獨的文檔,所以對於唯一的多鍵索引,文檔可能具有導致重複索引鍵值的數組元素,只要該文檔的索引鍵值不重複另一個文檔的索引鍵值即可。

有關更多信息,請參見跨單獨文檔的唯一約束

 

四、侷限性

1.複合多鍵索引

對於複合多鍵索引,每個索引文檔最多可以有一個值是數組的索引字段,其。即:

 

  • 如果文檔的一個以上的值是組數的字段要創建索引,則無法創建複合多鍵索引。例如,考慮一個包含以下文檔的集合:
{ _id: 1, a: [ 1, 2 ], b: [ 1, 2 ], category: "AB - both arrays" }

       則不能在集合上創建複合多鍵索引{a:1,b:1},因爲a和b字段都是數組。

 

  • 或者,如果已經存在複合多鍵索引,則不能插入違反此限制的文檔。

       考慮一個包含以下文檔的集合:       

{ _id: 1, a: [1, 2], b: 1, category: "A array" }

{ _id: 2, a: 1, b: [1, 2], category: "B array" }

      允許使用複合多鍵索引{a:1,b:1},因爲對於每個文檔,複合多鍵索引只有一個字段是一個數組。即沒有文檔的a和b字段值同時是數組。

      但是,在創建複合多鍵索引之後,如果您嘗試插入a和b字段均爲數組的文檔,則MongoDB將使插入失敗。

      如果字段是數組,並且數組的字段是嵌入式的,則嵌入式的字段也可以創建複合索引。例如,考慮一個包含以下文檔的集合:

{ _id: 1, a: [ { x: 5, z: [ 1, 2 ] }, { z: [ 1, 2 ] } ] }

{ _id: 2, a: [ { x: 5 }, { z: 4 } ] }

您可以在{“ a.x”:1,“ a.z”:1}上創建複合索引。最多只能有一個索引字段可以是數組的限制也適用。

有關示例,請參見帶有嵌入式文檔的索引數組

也可以看看

 

2.排序

由於MongoDB 3.6中對數組字段的排序行爲發生了變化,因此在對使用多鍵索引建立索引的數組上進行排序時,查詢計劃包括一個阻塞的SORT階段。新的排序行爲可能會對性能產生負面影響。

在阻塞式SORT中,必須在排序過程中使用所有輸入參數,然後才能產生輸出。在非阻塞或索引排序中,排序過程會掃描索引以按請求的順序產生結果。

 

3.分片鍵

不能將多鍵索引指定爲分片鍵索引。

但是,如果分片鍵索引是複合索引的前綴,並且如果其他鍵(即不屬於分片鍵的鍵)是對數組建立的索引,則允許該複合索引成爲複合多鍵索引。複合多鍵索引可能會影響性能

 

4.哈希索引

哈希索引不能爲多鍵。

5.覆蓋查詢

多鍵索引不能覆蓋對數組字段的查詢。

但是,從3.6開始,如果索引跟蹤哪個字段或哪些字段導致索引成爲多鍵,則多鍵索引可以覆蓋非數組字段的查詢。在MongoDB 3.4或更高版本中在MMAPv1 [#] _以外的存儲引擎上創建的多鍵索引會跟蹤此數據。

[2]從4.2版開始,MongoDB刪除了不贊成使用的MMAPv1存儲引擎。

6.整體查詢數組字段

當查詢過濾器指定整個數組的完全匹配項時,MongoDB可以使用多鍵索引查找查詢數組的第一個元素,但不能使用多鍵索引掃描來查找整個數組。相反,在使用多鍵索引查找數組的第一個元素之後,MongoDB檢索關聯的文檔並過濾其數組與查詢中的數組匹配的文檔。

例如,考慮包含以下文檔的庫存收集:

{ _id: 5, type: "food", item: "aaa", ratings: [ 5, 8, 9 ] }

{ _id: 6, type: "food", item: "bbb", ratings: [ 5, 9 ] }

{ _id: 7, type: "food", item: "ccc", ratings: [ 9, 5, 8 ] }

{ _id: 8, type: "food", item: "ddd", ratings: [ 9, 5 ] }

{ _id: 9, type: "food", item: "eee", ratings: [ 5, 9, 5 ] }

該集合在ratings 字段上具有多鍵索引:

db.inventory.createIndex( { ratings: 1 } )

以下查詢查找評級字段爲數組[5,9]的文檔:

db.inventory.find( { ratings: [ 5, 9 ] } )

MongoDB可以使用多鍵索引查找在ratings數組中具有5的文檔。然後,MongoDB檢索這些文檔並過濾其ratings 數組等於查詢數組[5、9]的文檔。

 

7.$ expr

$ expr不支持多鍵索引。

 

五、例子

1.基本數組索引

考慮包含以下文檔的survey集合

{ _id: 1, item: "ABC", ratings: [ 2, 5, 9 ] }

在字段ratings上創建索引:

db.survey.createIndex( { ratings: 1 } )

由於ratings 字段包含一個數組,因此ratings 索引是多鍵的。該多鍵索引包含以下三個索引鍵,每個都指向同一文檔:

  • 2,
  • 5,
  • 9。

2.帶有嵌入式文檔的索引數組

您可以在包含嵌套對象的數組字段上創建多鍵索引。

考慮具有以下格式文檔的inventory集合

{

  _id: 1,

  item: "abc",

  stock: [

    { size: "S", color: "red", quantity: 25 },

    { size: "S", color: "blue", quantity: 10 },

    { size: "M", color: "blue", quantity: 50 }

  ]

}

{

  _id: 2,

  item: "def",

  stock: [

    { size: "S", color: "blue", quantity: 20 },

    { size: "M", color: "blue", quantity: 5 },

    { size: "M", color: "black", quantity: 10 },

    { size: "L", color: "red", quantity: 2 }

  ]

}

{

  _id: 3,

  item: "ijk",

  stock: [

    { size: "M", color: "blue", quantity: 15 },

    { size: "L", color: "blue", quantity: 100 },

    { size: "L", color: "red", quantity: 25 }

  ]

}

...

以下操作在stock.sizestock.quantity字段上創建多鍵索引:

db.inventory.createIndex( { "stock.size": 1, "stock.quantity": 1 } )

複合多鍵索引可以支持包含索引字段的查詢,也支持僅包含索引前綴“ stock.size”的查詢,如以下示例所示:

db.inventory.find( { "stock.size": "M" } )

db.inventory.find( { "stock.size": "S", "stock.quantity": { $gt: 20 } } )

有關MongoDB如何組合多鍵索引範圍的詳細信息,請參閱多鍵索引範圍。有關複合索引和前綴的行爲的更多信息,請參見複合索引和前綴

複合多鍵索引還可以支持排序操作,例如以下示例:

db.inventory.find( ).sort( { "stock.size": 1, "stock.quantity": 1 } )

db.inventory.find( { "stock.size": "M" } ).sort( { "stock.quantity": 1 } )

有關複合索引和排序操作的行爲的更多信息,請參見使用索引對查詢結果進行排序

 

上一篇:複合索引

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