翻译或纠错本页面

多键索引

为了索引一个储存数组的键,MongoDB对数组中的每个元素都添加索引项。当收到查询时,这些 多键索引 让MongoDB可以利用数组的值返回相应文档作为结果。MongoDB会自动地 决定是否需要创建一个多键索引,如果这个键存储着数组。您不需要显示地指定索引为多键类型。

Diagram of a multikey index on the ``addr.zip`` field. The ``addr`` field contains an array of address documents. The address documents contain the ``zip`` field.

Create Multikey Index

To create a multikey index, use the db.collection.createIndex() method:

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

多键索引所支持的操作和MongoDB里其他索引一样。此外,应用还可以使用多键索引根据被索引数组中元素的值域范围来选取文档。多键索引可以索引的数组中,元素可以是值(例如 字符串,数字等),还可以是内嵌文档。

Index Bounds

If an index is multikey, then computation of the index bounds follows special rules. For details on multikey index bounds, see Multikey Index Bounds.

限制

Compound Multikey Indexes

For a compound multikey index, each indexed document can have at most one indexed field whose value is an array. As such, you cannot create a compound multikey index if more than one to-be-indexed field of a document is an array. Or, if a compound multikey index already exists, you cannot insert a document that would violate this restriction.

您可以创建一个包含有多键索引的 复合索引 ,但是在复合索引中最多只能有一个多键索引。例如,有一个索引 { a: 1, b: 1 }, 以下的文档是允许的:

{ _id: 1, a: [ 1, 2 ], b: [ 1, 2 ], category: "AB - both arrays" }

但是,如下的文档就是不被允许的,而且MongoDB将不会把这样的一个文档存储到集合中并建立索引 {a: 1, b: 1 }

But consider a collection that contains the following documents:

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

A compound multikey index { a: 1, b: 1 } is permissible since for each document, only one field indexed by the compound multikey index is an array; i.e. no document contains array values for both a and b fields. After creating the compound multikey index, if you attempt to insert a document where both a and b fields are arrays, MongoDB will fail the insert.

分片键

You cannot specify a multikey index as the shard key index.

在 2.6 版更改: However, if the shard key index is a prefix of a compound index, the compound index is allowed to become a compound multikey index if one of the other keys (i.e. keys that are not part of the shard key) indexes an array. Compound multikey indexes can have an impact on performance.

哈希键

Hashed indexes cannot be multikey.

Covered Queries

为了计算一个 哈希 索引键的哈希值,MongoDB会折叠子文档并计算其整体的哈希值。所以,对于那些存储着子文档数组的键,您无法使用(哈希且多键)索引来满足那些需要匹配子文档内部的查询。

Query on the Array Field as a Whole

When a query filter specifies an exact match for an array as a whole, MongoDB can use the multikey index to look up the first element of the query array but cannot use the multikey index scan to find the whole array. Instead, after using the multikey index to look up the first element of the query array, MongoDB retrieves the associated documents and filters for documents whose array matches the array in the query.

For example, consider an inventory collection that contains the following documents:

{ _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 ] }

The collection has a multikey index on the ratings field:

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

The following query looks for documents where the ratings field is the array [ 5, 9 ]:

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

MongoDB can use the multikey index to find documents that have 5 at any position in the ratings array. Then, MongoDB retrieves these documents and filters for documents whose ratings array equals the query array [ 5, 9 ].

例子

索引简单数组

Consider a survey collection with the following document:

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

Create an index on the field ratings:

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

tags 键创建的索引 { tags: 1 } ,将会建立一个多键索引,并且会包含如下四个独立索引项:

  • 2,
  • 5, and
  • 9.

Index Arrays with Embedded Documents

You can create multikey indexes on array fields that contain nested objects.

Consider an inventory collection with documents of the following form:

{
  _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 }
  ]
}

...

The following operation creates a multikey index on the stock.size and stock.quantity fields:

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

The compound multikey index can support queries with predicates that include both indexed fields as well as predicates that include only the index prefix "stock.size", as in the following examples:

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

comments.text 上建立的索引将会是一个多键索引,并且会为数组中每个元素在索引中添加一个索引项。

假使在集合 feedback 上有了索引 { "comments.text": 1 } ,考虑如下查询:

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

这条查询将会在集合中筛选出在 comments 数组中包含有如下内嵌文档的文档。