Docs HomeMongoDB Manual

Multikey Indexes多键索引

To index a field that holds an array value, MongoDB creates an index key for each element in the array. 为了索引包含数组值的字段,MongoDB为数组中的每个元素创建一个索引键。These multikey indexes support efficient queries against array fields. 这些多键索引支持针对数组字段的高效查询。Multikey indexes can be constructed over arrays that hold both scalar values [1] (e.g. strings, numbers) and nested documents.可以在既包含标量值[1](例如字符串、数字)又包含嵌套文档的数组上构造多键索引。

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.
[1] A scalar value refers to value that is neither an embedded document nor an array.标量值是指既不是嵌入文档也不是数组的值。

Create Multikey Index创建多键索引

To create a multikey index, use the db.collection.createIndex() method:要创建多键索引,请使用db.collection.createIndex()方法:

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

MongoDB automatically creates a multikey index if any indexed field is an array; you do not need to explicitly specify the multikey type.如果任何索引字段是数组,MongoDB会自动创建一个多键索引;您不需要显式指定多键类型。

Note

For the WiredTiger and In-Memory storage engines only,仅用于WiredTiger和In-Memory存储引擎

For multikey indexes, MongoDB keeps track of which indexed field or fields cause an index to be a multikey index. 对于多键索引,MongoDB会跟踪哪个或哪些索引字段导致索引成为多键索引。Tracking this information allows the MongoDB query engine to use tighter index bounds.通过跟踪这些信息,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.有关多键索引边界的详细信息,请参阅多键索引界限

Unique Multikey Index唯一的多键索引

For unique indexes, the unique constraint applies across separate documents in the collection rather than within a single document.对于唯一索引,唯一约束适用于集合中的单独文档,而不是单个文档中。

Because the unique constraint applies to separate documents, for a unique multikey index, a document may have array elements that result in repeating index key values as long as the index key values for that document do not duplicate those of another document.由于唯一约束适用于单独的文档,因此对于唯一的多键索引,只要该文档的索引关键字值不与另一文档的索引键值重复,该文档就可能具有导致重复索引关键字值的数组元素。

For more information, see Unique Constraint Across Separate Documents.有关详细信息,请参阅跨单独文档的唯一约束

Limitations局限性

Compound Multikey Indexes复合多键索引

For a compound multikey index, each indexed document can have at most one indexed field whose value is an array. 对于复合多键索引,每个索引文档最多可以有一个索引字段,其值为数组。That is:即:

  • You cannot create a compound multikey index if more than one to-be-indexed field of a document is an array. 如果文档的多个待索引字段是数组,则不能创建复合多键索引。For example, consider a collection that contains the following document:例如,考虑一个包含以下文档的集合:

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

    You cannot create a compound multikey index { a: 1, b: 1 } on the collection since both the a and b fields are arrays.由于ab字段都是数组,因此无法在集合上创建复合多键索引{ a: 1, b: 1 }

  • Or, if a compound multikey index already exists, you cannot insert a document that would violate this restriction.或者,如果复合多键索引已经存在,则不能插入违反此限制的文档。

    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.允许使用复合关键字索引{ a: 1, b: 1 },因为对于每个文档,只有一个由复合关键字索引索引的字段是数组;即没有文档同时包含ab字段的数组值。

    However, 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.但是,在创建复合多键索引后,如果您试图插入一个ab字段都是数组的文档,MongoDB将无法插入。

If a field is an array of documents, you can index the embedded fields to create a compound index. 如果字段是文档数组,则可以对嵌入的字段进行索引以创建复合索引。For example, consider a collection that contains the following documents:例如,考虑一个包含以下文档的集合:

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

You can create a compound index on { "a.x": 1, "a.z": 1 }. 您可以在{ "a.x": 1, "a.z": 1 }上创建复合索引。The restriction where at most one indexed field can be an array also applies.最多一个索引字段可以是数组的限制也适用。

For an example, see Index Arrays with Embedded Documents.有关示例,请参阅带嵌入式文档的索引数组

Sorting排序

As a result of changes to sorting behavior on array fields in MongoDB 4.4, when you sort on an array indexed with a multikey index, the query plan includes a blocking sort stage, unless:由于MongoDB 4.4中对数组字段排序行为的更改,当您对使用多键索引索引的数组进行排序时,查询计划包括阻塞排序阶段,除非:

  • The index boundaries for all sort fields are [MinKey, MaxKey], and所有排序字段的索引边界[MinKey, MaxKey],并且

  • No boundaries for any multikey-indexed field have the same path prefix as the sort pattern.任何多键索引字段的边界都不具有与排序模式相同的路径前缀。

Shard Keys分片键

You cannot specify a multikey index as the shard key index.不能将多键索引指定为分片关键字索引。

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. 但是,如果分片键索引是复合索引的前缀,则如果其他键之一(即不属于shard键的键)对数组进行索引,则允许复合索引成为复合多键索引。Compound multikey indexes can have an impact on performance.复合多键索引可能会对性能产生影响。

Hashed Indexes哈希索引

Hashed indexes cannot be multikey.哈希索引不能是多键。

Covered Queries涵盖的查询

Multikey indexes cannot cover queries over array field(s).多键索引无法覆盖对数组字段的查询。

Multikey indexes can cover queries over non-array fields if the index tracks which field or fields cause the index to be multikey.如果索引跟踪导致索引为多键的字段,则多键索引可以覆盖对非数组字段的查询。

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. 当查询筛选器指定为对整个数组完全匹配时,MongoDB可以使用多键索引来查找查询数组的第一个元素,但不能使用多键指数扫描来查找整个数组。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.相反,在使用多键索引查找查询数组的第一个元素后,MongoDB检索关联的文档,并筛选数组与查询中的数组匹配的文档。

For example, consider an inventory collection that contains the following documents:例如,考虑包含以下文档的inventory集合:

{ _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:该集合在ratings字段上有一个多键索引:

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

The following query looks for documents where the ratings field is the array [ 5, 9 ]:以下查询查找ratings字段为数组[ 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. MongoDB可以使用多键索引来查找ratings数组中任何位置都有5的文档。Then, MongoDB retrieves these documents and filters for documents whose ratings array equals the query array [ 5, 9 ].然后,MongoDB检索这些文档,并筛选ratings数组等于查询数组[ 5, 9 ]的文档。

$expr

$expr does not support multikey indexes.不支持多键索引。

Examples实例

Index Basic Arrays索引基本数组

Create a survey collection with the following document:使用以下文档创建survey集合:

db.survey.insertOne(
{ _id: 1, item: "ABC", ratings: [ 2, 5, 9 ] }
)

Create an index on the field ratings:创建字段ratings索引:

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

Since the ratings field contains an array, the index on ratings is multikey. 由于ratings字段包含一个数组,因此ratings索引是多键的。The multikey index contains the following three index keys, each pointing to the same document:多关键字索引包含以下三个索引关键字,每个索引关键字指向同一文档:

  • 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:考虑使用以下形式的文档的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 }
]
}

...

The following operation creates a multikey index on the stock.size and stock.quantity fields:以下操作在stock.sizestock.quantity字段上创建一个多键索引:

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:复合多键索引可以支持具有谓词的查询,这些谓词既包括索引字段,也包括仅包括索引前缀"stock.size"的谓词,如以下示例所示:

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

For details on how MongoDB can combine multikey index bounds, see Multikey Index Bounds. 有关MongoDB如何组合多关键字索引边界的详细信息,请参阅多关键字索引边界For more information on behavior of compound indexes and prefixes, see compound indexes and prefixes.有关复合索引和前缀行为的详细信息,请参阅复合索引和后缀

The compound multikey index can also support sort operations, such as the following examples:复合多关键字索引还可以支持排序操作,例如以下示例:

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

For more information on behavior of compound indexes and sort operations, see Use Indexes to Sort Query Results.有关复合索引行为和排序操作的详细信息,请参阅使用索引对查询结果进行排序