多键索引
多键索引是专门针对数组字段的, 会为数组字段的每一个元素都创建一个索引。
?> 插入测试数据:
db.person.insert([ {name:'as', age:18, tags:['ahtml', 'bcss']}, {name:'bs', age:17, tags:['cjs', 'enode']}, {name:'cs', age:19, tags:[ 'dvue', 'freact']}, ])
首先来看看我们没有创建多键索引之前的查询效果:
db.person.explain().find({'tags':{$in:['ahtml']}})
从如下结果集返回来看,是一个全表扫描的情况:
{ "queryPlanner" : { "plannerVersion" : 1, "namespace" : "test.person", "indexFilterSet" : false, "parsedQuery" : { "tags" : { "$eq" : "ahtml" } }, "winningPlan" : { "stage" : "COLLSCAN", "filter" : { "tags" : { "$eq" : "ahtml" } }, "direction" : "forward" }, "rejectedPlans" : [ ] }, "serverInfo" : { "host" : "LAPTOP-A8CAC6IT", "port" : 27017, "version" : "4.0.28", "gitVersion" : "af1a9dc12adcfa83cc19571cb3faba26eeddac92" }, "ok" : 1 }
创建多键索引:
db.person.createIndex({tags:1})
再次进行查询:
db.person.explain().find({'tags':{$in:['ahtml']}})
返回结果:
{ "queryPlanner" : { "plannerVersion" : 1, "namespace" : "test.person", "indexFilterSet" : false, "parsedQuery" : { "tags" : { "$eq" : "ahtml" } }, "winningPlan" : { "stage" : "FETCH", "inputStage" : { "stage" : "IXSCAN", "keyPattern" : { "tags" : 1 }, "indexName" : "tags_1", "isMultiKey" : true, "multiKeyPaths" : { "tags" : [ "tags" ] }, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 2, "direction" : "forward", "indexBounds" : { "tags" : [ "[\"ahtml\", \"ahtml\"]" ] } } }, "rejectedPlans" : [ ] }, "serverInfo" : { "host" : "LAPTOP-A8CAC6IT", "port" : 27017, "version" : "4.0.28", "gitVersion" : "af1a9dc12adcfa83cc19571cb3faba26eeddac92" }, "ok" : 1 }
很明显是通过索引进行命中对应的数据。
在我们创建了对应了多键索引之后,我们插入的测试数据对应的数据结构大概的体系结构如下可以进行稍微了解了解:
'ahtml' -> {name:'as', age:18, tags:['ahtml', 'bcss']} 'bcss' -> {name:'as', age:18, tags:['ahtml', 'bcss']} 'cjs' -> {name:'bs', age:17, tags:['cjs', 'enode']} 'dvue' -> {name:'cs', age:19, tags:[ 'dvue', 'freact']} 'enode' -> {name:'bs', age:17, tags:['cjs', 'enode']} 'freact' -> {name:'cs', age:19, tags:[ 'dvue', 'freact']}