多键索引从包含数组值的字段中收集数据并进行排序。多键索引可提高对数组字段的查询性能。
当您在包含大量值的字段上创建索引时, MongoDB会自动将该索引设置为 多键索引。
MongoDB 可以在包含标量值(例如字符串和数字)和嵌入式文档的数组上创建多键索引。 如果数组包含同一值的多个实例,则索引仅包含该值的一个条目。
要创建多键索引,请使用以下原型:
db.<collection>.createIndex( { <arrayField>: <sortOrder> } )
下图显示了 addr.zip 字段的多键索引:
对于 MongoDB Atlas 中托管的部署,您可以 在用户界面中创建和管理多键索引。
用例
如果您的应用程序频繁查询包含数组值的字段,则多键索引可提高这些查询的性能。
示例,movies集合中的文档包含 genres字段:与每部电影相关的类型大量。您会定期查询具有特定类型的电影,例如查找所有同时为 Drama 和 Action 的电影。
您可对 genres 字段创建索引,从而为此查询提高性能。由于 genres 包含数组值,因此 MongoDB 会将该索引存储为多键索引。
开始体验
要创建多键索引,请参阅:
详情
本部分介绍多键索引的技术细节和限制。
本页上的示例使用 sample_mflix示例数据集中的数据。有关如何将此数据集加载到自管理MongoDB 部署中的详细信息,请参阅加载示例数据集。如果对示例数据库进行了任何修改,则可能需要删除并重新创建数据库才能运行本页上的示例。
索引边界
索引扫描的边界定义了查询期间要搜索的索引组成部分。多键索引边界的计算遵循特殊规则。有关详情,请参阅多键索引边界。
Unique Multikey Indexes
在唯一的多键索引中,只要一个文档的索引键值不与另一个文档的索引键值重复,该文档可能包含数组元素,这些元素就会导致索引键值重复。
要了解更多信息并查看此行为的示例,请参阅跨独立文档的唯一约束。
复合多键索引
在复合多键索引中,每个索引文档最多可以有一个值为数组的索引字段。具体而言:
如果索引规范中的多个字段是大量,则无法创建复合多键索引。
如果复合多键索引已存在,则无法插入会违反此限制的文档。
示例,您可以在 movies集合上创建复合多键索引{ genres: 1, year: 1
},因为对于每个文档,只有一个由复合多键索引的字段是大量。没有文档同时包含 genres 和 year 字段的大量值。
但是,在创建复合多键索引后,如果尝试插入 genres 和 year 字段均为数组的文档,则插入操作会失败。
排序
当您对使用多键索引的数组字段进行排序时,查询计划会包含一个内存排序阶段,除非以下两种情况均为真:
所有排序字段的索引边界均为
[MinKey, MaxKey]。任何多键已索引字段的边界均不得与排序模式的路径前缀相同。
分片键
您无法将多键索引指定为分片键索引。
但是,在分片键索引是复合索引前缀的情况下,如果尾随键之一(不是分片键的一部分)对数组进行索引,则复合索引可能会成为复合多键索引。
哈希(Hashed)索引
哈希索引不能是多键型。
覆盖查询
多键索引可以覆盖满足以下条件的查询:
查询不返回数组字段(这意味着该数组不包含在查询投影中)。这意味着要覆盖查询,多键索引必须是复合索引。
查询不包括
$elemMatch。该查询符合所有其他涵盖的查询要求。
示例,以下操作在 genres 和 title 字段的 movies集合上创建复合多键索引:
db.movies.createIndex( { genres: 1, title: 1 } )
前面的索引为多键索引,因为 genres 字段包含数组值。
该索引涵盖以下查询:
db.movies.find( { genres: 'Drama' }, { _id: 0, title: 1 } ).sort({ genres: 1 }).limit(5)
db.movies.find( { title: 'The Ace of Hearts', genres: 'Drama' }, { _id: 0, title: 1 } )
索引不包括以下查询,因为投影包含 genres 数组字段:
db.movies.find( { genres: 'Drama' }, { _id: 0, genres: 1 } ).limit(5)
对数组字段进行整体查询
当查询为整个大量指定精确匹配项时, MongoDB会使用多键索引来查找包含该大量第一个元素的文档。但是,仅使用索引无法匹配整个大量。然后, MongoDB获取候选文档并进行过滤,以仅返回数组与查询大量完全匹配的大量。
示例,以下操作在 genres字段的 movies集合上创建多键索引:
db.movies.createIndex( { genres: 1 } )
以下查询查找 genres 字段为数组 [ "Drama" ] 的文档:
db.movies.find( { genres: 'Drama' }, { title: 1, genres: 1 } ).limit(5)
MongoDB 可以使用多键索引来查找在 genres 数组中的任意位置包含 "Drama" 的文档。然后,MongoDB 检索这些文档并过滤出 genres 数组等于查询数组 [ "Drama" ] 的文档。
$expr
$expr 操作符不支持多键索引。