Quantcast
Channel: CodeSection,代码区,数据库(综合) - CodeSec
Viewing all articles
Browse latest Browse all 6262

MongoDB 多键索引

$
0
0

在MongoDB中可以基于数组来创建索引。MongoDB为数组每一个元素创建索引值。多键索引支持数组字段的高效查询。多键索引能够基于字符串,数字数组以及嵌套文档进行创建。本文主要描述多键索引并给出演示示例。

一、多键索引 基于一个数组创建索引,MongoDB会自动创建为多键索引,无需刻意指定 多键索引也可以基于内嵌文档来创建 多键索引的边界值的计算依赖于特定的规则 注,多键索引不等于在文档上的多列创建索引(复合索引) 创建语法 db.coll.createIndex( { <field>: < 1 or -1 > } ) 复合多键索引 对于一个复合多键索引,每个索引最多可以包含一个数组。 在多于一个数组的情形下来创建复合多键索引不被支持。 假定存在如下集合 { _id: 1, a: [ 1, 2 ], b: [ 1, 2 ], category: "AB - both arrays" } 不能基于一个基于{ a: 1, b: 1 } 的多键索引,因为a和b都是数组 假定存在如下集合 { _id: 1, a: [1, 2], b: 1, category: "A array" } { _id: 2, a: 1, b: [1, 2], category: "B array" } 则可以基于每一个文档创建一个基于{ a: 1, b: 1 }的复合多键索引 原因是每一个索引的索引字段只有一个数组 一些限制 不能够指定一个多键索引为分片片键索引 哈希索引不能够成为多键索引 多键索引不支持覆盖查询 基于整体查询数组字段 当一个查询筛选器将一个数组作为整体实现精确匹配时,MongoDB可以使用多键索引查找数组的第一个元素, 但不能使用多键索引扫描寻找整个数组。相反,使用多键索引查找查询数组的第一个元素后,MongoDB检索 相关文档并且过滤出那些复合匹配条件的文档。 二、示意图

如下图,基于集合上的数组创建多键索引,且数组为内嵌文档


MongoDB 多键索引
三、创建多键索引 1、演示环境 > db.version() 3.2.10 >db.inventory.insertMany([ { _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 ] }]) //下面基于ratings列创建一个多键索引 > db.inventory.createIndex( { ratings: 1 } ) { "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 } //查询数组上为5,9的文档 > db.inventory.find( { ratings: [ 5, 9 ] } ) { "_id" : 6, "type" : "food", "item" : "bbb", "ratings" : [ 5, 9 ] } //下面查看其执行计划 > db.inventory.find( { ratings: [ 5, 9 ] } ).explain() { "queryPlanner" : { ........ "inputStage" : { "stage" : "IXSCAN", "keyPattern" : { "ratings" : 1 }, "indexName" : "ratings_1", "isMultiKey" : true, //这里表明查询使用到了多键索引 ....... "direction" : "forward", "indexBounds" : { "ratings" : [ "[5.0, 5.0]", "[[ 5.0, 9.0 ], [ 5.0, 9.0 ]]" .......... "ok" : 1 } //在上面的示例中,使用了多键索引进行扫描,MongoDB寻找在ratings数组任意位置包含5的文档 //然后MongoDB检索这些文档,并过滤出那些等于[ 5, 9 ]的文档 2、基本索引数组 假定存在下列集合 { _id: 1, item: "ABC", ratings: [ 2, 5, 9 ] } 在ratings上创建索引 db.survey.createIndex( { ratings: 1 } ) 这个多键索引则包括2,5,9三个索引键,每一个分别指向相同的文档 3、基于内嵌文档的索引数组 //创建演示文档 > db.inventory.drop() > db.inventory.insertMany([ { _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", // Author : Leshami stock: [ // Blog : http://blog.csdn.net/leshami { 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 } ] }]) //下面基于内嵌文档的2个键来创建索引 > db.inventory.createIndex( { "stock.size": 1, "stock.quantity": 1 } ) { "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 } //查询内嵌文档stock.size为M的执行计划 > db.inventory.find( { "stock.size": "M" } ).explain() { "queryPlanner" : { ........ "winningPlan" : { "stage" : "FETCH", "inputStage" : { "stage" : "IXSCAN", //基于索引的扫描 "keyPattern" : { "stock.size" : 1, "stock.quantity" : 1 }, "indexName" : "stock.size_1_stock.quantity_1", ....... "indexBounds" : { "stock.size" : [ "[\"M\", \"M\"]" ], "stock.quantity" : [ "[MinKey, MaxKey]" ] } } }, } //基于内嵌文档2个键查询的执行计划 > db.inventory.find( { "stock.size": "S", "stock.quantity": { $gt: 20 } } ).explain() { "queryPlanner" : { .......... "winningPlan" : { "stage" : "FETCH", "filter" : { "stock.quantity" : { "$gt" : 20 } }, "inputStage" : { "stage" : "IXSCAN", //此时同样也使用到了索引扫描 "keyPattern" : { "stock.size" : 1, "stock.quantity" : 1 }, "indexName" : "stock.size_1_stock.quantity_1", "isMultiKey" : true, ......... "indexBounds" : { "stock.size" : [ "[\"S\", \"S\"]" ], "stock.quantity" : [ "[MinKey, MaxKey]" ............ "ok" : 1 } //基于内嵌数组排序查询 > db.inventory.find( ).sort( { "stock.size": 1, "stock.quantity": 1 } ).explain() { "queryPlanner" : { ........ "winningPlan" : { "stage" : "FETCH", "inputStage" : { "stage" : "IXSCAN", //内嵌数组排序查询也使用到了索引 "keyPattern" : { "stock.size" : 1, "stock.quantity" : 1 }, "indexName" : "stock.size_1_stock.quantity_1", "isMultiKey" : true, ........... "indexBounds" : { "stock.size" : [ "[MinKey, MaxKey]" ], "stock.quantity" : [ "[MinKey, MaxKey]" ] } } }, "rejectedPlans" : [ ] }, } //基于内嵌数组一个键作为过滤,一个键作为排序查询的执行计划 > db.inventory.find( { "stock.size": "M" } ).sort( { "stock.quantity": 1 } ).explain() { "queryPlanner" : { .......... "winningPlan" : { "stage" : "FETCH", "inputStage" : { "stage" : "IXSCAN", "keyPattern" : { "stock.size" : 1, "stock.quantity" : 1 }, "indexName" : "stock.size_1_stock.quantity_1", "isMultiKey" : true, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 1, "direction" : "forward", "indexBounds" : { "stock.size" : [ "[\"M\", \"M\"]" ], "stock.quantity" : [ "[MinKey, MaxKey]" "rejectedPlans" : [ ] ....... "ok" : 1 }

更多参考

MongoDB 单键(列)索引 MongoDB 复合索引 MongoDB执行计划获取(db.collection.explain())
MongoDB 多键索引

Viewing all articles
Browse latest Browse all 6262

Trending Articles