多键索引¶
为了索引一个储存数组的键,MongoDB对数组中的每个元素都添加索引项。当收到查询时,这些 多键索引 让MongoDB可以利用数组的值返回相应文档作为结果。MongoDB会自动地 决定是否需要创建一个多键索引,如果这个键存储着数组。您不需要显示地指定索引为多键类型。
请看一下一个多键索引的示例:
多键索引所支持的操作和MongoDB里其他索引一样。此外,应用还可以使用多键索引根据被索引数组中元素的值域范围来选取文档。多键索引可以索引的数组中,元素可以是值(例如 字符串,数字等),还可以是内嵌文档。
限制¶
复合索引和多键索引的结合¶
您可以创建一个包含有多键索引的 复合索引 ,但是在复合索引中最多只能有一个多键索引。例如,有一个索引 { a: 1, b: 1 }, 以下的文档是允许的:
{a: [1, 2], b: 1}
{a: 1, b: [1, 2]}
但是,如下的文档就是不被允许的,而且MongoDB将不会把这样的一个文档存储到集合中并建立索引 {a: 1, b: 1 } :
{a: [1, 2], b: [1, 2]}
如果您尝试插入这样一个文档,MongoDB将会拒绝插入并产生这样的错误 不能并行索引数组 。MongoDB不并行索引数组是因为它们要求索引要包含复合键的笛卡尔积(Cartesian product)中的每个值,这么做会导致索引变得极其大且难以维护。
分片键¶
重要
分片键的索引 不能 是一个多键索引
哈希键¶
哈希 索引和多键索引无法适配。
为了计算一个 哈希 索引键的哈希值,MongoDB会折叠子文档并计算其整体的哈希值。所以,对于那些存储着子文档数组的键,您无法使用(哈希且多键)索引来满足那些需要匹配子文档内部的查询。
例子¶
索引简单数组¶
假设有如下文档:
{
"_id" : ObjectId("..."),
"name" : "Warm Weather",
"author" : "Steve",
"tags" : [ "weather", "hot", "record", "april" ]
}
对 tags 键创建的索引 { tags: 1 } ,将会建立一个多键索引,并且会包含如下四个独立索引项:
- "weather",
- "hot",
"record" ,和
- "april".
查询可以根据上述任一值,使用多键索引返回结果。
索引含有内嵌文档的数组¶
如下例所示,您可以在存储着对象数组的键上创建多键索引。
假设在 feedback 集合中有如下文档:
{
"_id": ObjectId(...),
"title": "Grocery Quality",
"comments": [
{ author_id: ObjectId(...),
date: Date(...),
text: "Please expand the cheddar selection." },
{ author_id: ObjectId(...),
date: Date(...),
text: "Please expand the mustard selection." },
{ author_id: ObjectId(...),
date: Date(...),
text: "Please expand the olive selection." }
]
}
在 comments.text 上建立的索引将会是一个多键索引,并且会为数组中每个元素在索引中添加一个索引项。
假使在集合 feedback 上有了索引 { "comments.text": 1 } ,考虑如下查询:
db.feedback.find( { "comments.text": "Please expand the olive selection." } )
这条查询将会在集合中筛选出在 comments 数组中包含有如下内嵌文档的文档。
{ author_id: ObjectId(...),
date: Date(...),
text: "Please expand the olive selection." }