复合索引¶
MongoDB支持 复合索引 ,其中每个索引项可以包含有集合中文档的多个键 [1] 。下图是一个具有两个键的复合索引的例子:
[1] | MongoDB允许 复合索引最多31个键。 |
复合索引可以支持要求匹配多个键的查询。
例子
假设有个叫 products 的集合包含了如下文档:
{
"_id": ObjectId(...),
"item": "Banana",
"category": ["food", "produce", "grocery"],
"location": "4th Street Store",
"stock": 4,
"type": "cases",
"arrival": Date(...)
}
如果应用需要查询 item 键,有时也需要同时查询 item 和 stock 键,那么您可以创建一个复合索引来同时支持这些查询,如下:
db.products.ensureIndex( { "item": 1, "stock": 1 } )
重要
您不能基于 hashed 键创建索引。您将会收到错误如果您尝试在复合索引里包含 哈希索引。
复合索引中键的顺序是非常重要的。在前面的一个例子中,索引会首先根据 item 键的值对文档排序,其次在 item 相同的情况下再根据 stock 的值对文档排序。参见 排序顺序 了解详情。
复合索引支持匹配所有被索引键的查询,除此之外还支持查询被索引键的前缀。点击 前缀 了解细节。
排序顺序¶
索引以两种顺序存储键,升序 (1) 或降序 (-1)。对于单键索引而言,键的顺序无关紧要因为MongoDB可以以任一顺序便利整个索引。但是对于 复合索引 而言,索引的顺序可以决定索引是否支持直接排序操作(而不需要而外附加一个排序阶段)。
假设有一个集合名叫 events ,其中文档包含有 username and date 键。应用可以发起一个查询请求要求结果按照 username 键升序而且 date 键将需 (比如,更多的最近更新数据),如下:
db.events.find().sort( { username: 1, date: -1 } )
或者查询要求结果按照 username 键降序然后 date 键升序,如下:
db.events.find().sort( { username: -1, date: 1 } )
那么,下面的这个索引就可以同时支持这两种排序操作:
db.events.ensureIndex( { "username" : 1, "date" : -1 } )
但是,上述的索引 不能 支持先按照 username 键升序再按照 date 升序这样的请求,如下:
db.events.find().sort( { username: 1, date: 1 } )
前缀¶
复合索引支持匹配被索引键的任何前缀的查询。这里的前缀是指被索引键的起始子集部分,比如给定索引 { a: 1, b: 1, c: 1 },那么 { a: 1 } 和 { a: 1, b: 1 } 都是它的前缀。
如果您的集合有一个复合索引 { a: 1, b: 1 },此外还有一个索引包含了前述复合索引的前缀部分,比如 { a: 1 },假设这两个索引都没有系数或者唯一性方面的限制,那么您可以移除 { a: 1 } 索引。因为在所有可以使用 { a: 1 } 索引的场合里,MongoDB都将会使用前述复合索引。
比如,假设有如下索引
{ "item": 1, "location": 1, "stock": 1 }
MongoDB 可以 可以使用这个索引来支持匹配如下条件的查询:
包含 item 键,或者
包含 item 和 location 键,或者
包含 item 和 location 以及 stock 键,或者
只是 item 和 stock 键;但是,这种情况下,索引将不如只包含 item 和 stock 键的索引高效。
MongoDB 不能 使用这个索引来支持下述查询:
只有 location 键,
只有 stock 键,或者
只有 location 和 stock 键。