Docs HomeDevelop ApplicationsMongoDB Manual

Multikey Indexes多键索引

Multikey indexes collect and sort data from fields containing array values. 多键索引从包含数组值的字段中集合数据并对其进行排序。Multikey indexes improve performance for queries on array fields.多键索引提高了对数组字段的查询性能。

You do not need to explicitly specify the multikey type. 您不需要显式指定多键类型。When you create an index on a field that contains an array value, MongoDB automatically sets that index to be a multikey index.当您在包含数组值的字段上创建索引时,MongoDB会自动将该索引设置为多键索引。

MongoDB can create multikey indexes over arrays that hold both scalar values (for example, strings and numbers) and embedded documents.MongoDB可以在包含标量值(例如字符串和数字)和嵌入文档的数组上创建多键索引。

To create a multikey index, use the following prototype:要创建多键索引,请使用以下原型:

db.<collection>.createIndex( { <arrayField>: <sortOrder> } )

This image shows a multikey index on the addr.zip field:此图显示addr.zip字段上的多键索引:

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.

Use Cases用例

If your application frequently queries a field that contains an array value, a multikey index improves performance for those queries.如果应用程序经常查询包含数组值的字段,则多键索引可以提高这些查询的性能。

For example, documents in a students collection contain a test_scores field: an array of test scores a student received throughout the semester. 例如,students集合中的文档包含一个test_scores字段:学生在整个学期中收到的测试分数的数组。You regularly update a list of top students: students who have at least five test_scores greater than 90.你会定期更新一份顶尖学生名单:至少有五个test_scores超过90的学生。

You can create an index on the test_scores field to improve performance for this query. 您可以在test_scores字段上创建索引,以提高此查询的性能。Because test_scores contains an array value, MongoDB stores the index as a multikey index.因为test_scores包含一个数组值,所以MongoDB将索引存储为一个多键索引。

Get Started起步

To create a multikey index, see:要创建多键索引,请参阅:

Details详细信息

This section describes technical details and limitations for multikey indexes.本节介绍了多键索引的技术细节和限制。

Index Bounds索引边界

The bounds of an index scan define the parts of an index to search during a query. 索引扫描的边界定义了在查询过程中要搜索的索引部分。The computation of multikey index bounds follows special rules. 多键索引边界的计算遵循特殊规则。For details, see Multikey Index Bounds.有关详细信息,请参阅多键索引边界

Unique Multikey Indexes唯一多键索引

In 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.唯一的多键索引中,只要文档的索引键值不与另一文档的索引键值重复,文档就可能具有导致重复索引键值的数组元素。

To learn more and see an example of this behavior, see Unique Constraint Across Separate Documents.若要了解更多信息并查看此行为的示例,请参阅跨单独文档的唯一约束

Compound Multikey Indexes复合多键索引

In a compound multikey index, each indexed document can have at most one indexed field whose value is an array. 复合多键索引中,每个索引文档最多可以有一个索引字段,其值为数组。Specifically:具体而言:

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

    { _id: 1, scores_spring: [ 8, 6 ], scores_fall: [ 5, 9 ] }

    You can't create the compound multikey index { scores_spring: 1, scores_fall: 1 } because both fields in the index are arrays.不能创建复合多键索引{ scores_spring: 1, scores_fall: 1 },因为索引中的两个字段都是数组。

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

    Consider a collection that contains these documents:考虑一个包含以下文档的集合:

    { _id: 1, scores_spring: [8, 6], scores_fall: 9 }
    { _id: 2, scores_spring: 6, scores_fall: [5, 7] }

    You can create a compound multikey index { scores_spring: 1, scores_fall: 1 } because for each document, only one field indexed by the compound multikey index is an array. 您可以创建一个复合多键索引{ scores_spring: 1, scores_fall: 1 },因为对于每个文档,只有一个由复合多键指数索引的字段是数组。No document contains array values for both scores_spring and scores_fall fields.没有文档同时包含scores_springscores_fall字段的数组值。

    However, after you create the compound multikey index, if you attempt to insert a document where both scores_spring and scores_fall fields are arrays, the insert fails.但是,在创建复合多键索引后,如果您试图插入一个scores_springscores_fall字段都是数组的文档,则插入操作将失败。

Sorting排序

When you sort based on an array field that is indexed with a multikey index, the query plan includes a blocking sort stage unless both of the following are true:当您根据使用多键索引进行索引的数组字段进行排序时,除非以下两项均为真,否则查询计划将包括一个阻塞排序阶段:

  • The index boundaries for all sort fields are [MinKey, MaxKey].所有排序字段的索引边界都[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 a shard key index.不能将多键索引指定为分片键索引。

However, if the shard key index is a prefix of a compound index, the compound index may become a compound multikey index if one of the trailing keys (that are not part of the shard key) indexes an array.但是,如果分片键索引是复合索引的前缀,则如果某个尾随键(不是分片键的一部分)对数组进行索引,则复合索引可能会变成复合多键索引。

Hashed Indexes哈希索引

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

Covered Queries涵盖的查询

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

For example, consider a matches collection with these documents:例如,考虑具有以下文档的matches集合:

db.matches.insertMany( [
{ name: "joe", event: ["open", "tournament"] },
{ name: "bill", event: ["match", "championship"] }
] )

The matches collection has a compound multikey index on the name and event fields:matches集合在name字段和event字段上有一个复合多键索引:

db.matches.createIndex( { name: 1, event: 1 } )

This index is a multikey index because the event field contains array values.此索引是一个多键索引,因为event字段包含数组值。

The multikey index covers the following query, even though the matched field (name) is not an array:即使匹配的字段(name)不是数组,多键索引也涵盖以下查询:

db.matches.find( { name: "bill" } )

Because name field is part of the index prefix, the index covers queries on the name field. 由于name字段是索引前缀的一部分,因此索引涵盖了对name字段的查询。The index cannot cover queries on both name and event, because multikey indexes cannot cover queries on array fields.索引不能同时覆盖nameevent的查询,因为多键索引不能覆盖数组字段的查询。

Query on an 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 these documents:例如,考虑一个包含以下文档的inventory集合:

db.inventory.insertMany( [
{ _id: 5, type: "food", item: "apple", ratings: [ 5, 8, 9 ] }
{ _id: 6, type: "food", item: "banana", ratings: [ 5, 9 ] }
{ _id: 7, type: "food", item: "chocolate", ratings: [ 9, 5, 8 ] }
{ _id: 8, type: "food", item: "fish", ratings: [ 9, 5 ] }
{ _id: 9, type: "food", item: "grapes", ratings: [ 5, 9, 5 ] }
] )

The inventory collection has a multikey index on the ratings field:inventory集合在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

The $expr operator does not support multikey indexes.$expr运算符不支持多键索引。

Learn More了解更多信息