MongoDB在排序时在组件索引中滥用地理空间索引
我转到Mongo命令行(版本4.4.1)并执行以下操作 结果表明,虽然查询(按位置查找和按类别排序)有一个完美的匹配,但没有使用索引(位置,类别2)。 获奖计划显示使用了类别1索引: “索引名称”:“位置、范围、类别1”MongoDB在排序时在组件索引中滥用地理空间索引,mongodb,mongodb-query,multi-index,Mongodb,Mongodb Query,Multi Index,我转到Mongo命令行(版本4.4.1)并执行以下操作 结果表明,虽然查询(按位置查找和按类别排序)有一个完美的匹配,但没有使用索引(位置,类别2)。 获奖计划显示使用了类别1索引: “索引名称”:“位置、范围、类别1” db.places.find({ location: { $near: { $geometry: { type: "Point", coordinates: [ 0, 0 ] } } } }).sort({ category2 : 1 }).explai
db.places.find({ location: { $near: { $geometry: { type: "Point", coordinates: [ 0, 0 ] } } } }).sort({ category2 : 1 }).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "dev.places",
"indexFilterSet" : false,
"parsedQuery" : {
"location" : {
"$near" : {
"$geometry" : {
"type" : "Point",
"coordinates" : [
0,
0
]
}
}
}
},
"queryHash" : "8766F2A3",
"planCacheKey" : "9B5661A5",
"winningPlan" : {
"stage" : "SORT",
"sortPattern" : {
"category2" : 1
},
"memLimit" : 104857600,
"type" : "simple",
"inputStage" : {
"stage" : "GEO_NEAR_2DSPHERE",
"keyPattern" : {
"location" : "2dsphere",
"category1" : 1
},
"indexName" : "location_2dsphere_category1_1",
"indexVersion" : 2,
"inputStage" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"location" : "2dsphere",
"category1" : 1
},
"indexName" : "location_2dsphere_category1_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"location" : [ ],
"category1" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"location" : [
"[-9223372036854775807, -6917529027641081857]",
"[-6917529027641081855, -4611686018427387905]",
"[1, 2305843009213693951]",
"[2305843009213693953, 4611686018427387903]",
"[4611686018427387905, 6917529027641081855]",
"[6917529027641081857, 9223372036854775807]"
],
"category1" : [
"[MinKey, MaxKey]"
]
}
}
}
}
},
"rejectedPlans" : [
{
"stage" : "SORT",
"sortPattern" : {
"category2" : 1
},
"memLimit" : 104857600,
"type" : "simple",
"inputStage" : {
"stage" : "GEO_NEAR_2DSPHERE",
"keyPattern" : {
"location" : "2dsphere",
"category2" : 1
},
"indexName" : "location_2dsphere_category2_1",
"indexVersion" : 2,
"inputStage" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"location" : "2dsphere",
"category2" : 1
},
"indexName" : "location_2dsphere_category2_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"location" : [ ],
"category2" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"location" : [
"[-9223372036854775807, -6917529027641081857]",
"[-6917529027641081855, -4611686018427387905]",
"[1, 2305843009213693951]",
"[2305843009213693953, 4611686018427387903]",
"[4611686018427387905, 6917529027641081855]",
"[6917529027641081857, 9223372036854775807]"
],
"category2" : [
"[MinKey, MaxKey]"
]
}
}
}
}
}
]
},
"serverInfo" : {
"host" : "XXXX",
"port" : 27017,
"version" : "4.4.1",
"gitVersion" : "ad91a93a5a31e175f5cbf8c69561e788bbc55ce1"
},
"ok" : 1
}
“获胜计划”:{
“阶段”:“排序”,
“排序模式”:{
“类别2”:1
},
“memLimit”:104857600,
“类型”:“简单”,
“输入阶段”:{
“舞台”:“地球仪近球”,
“按键模式”:{
“位置”:“2dsphere”,
“类别1”:1
},
“indexName”:“位置、范围和类别”,参见
db.places.find({ location: { $near: { $geometry: { type: "Point", coordinates: [ 0, 0 ] } } } }).sort({ category2 : 1 }).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "dev.places",
"indexFilterSet" : false,
"parsedQuery" : {
"location" : {
"$near" : {
"$geometry" : {
"type" : "Point",
"coordinates" : [
0,
0
]
}
}
}
},
"queryHash" : "8766F2A3",
"planCacheKey" : "9B5661A5",
"winningPlan" : {
"stage" : "SORT",
"sortPattern" : {
"category2" : 1
},
"memLimit" : 104857600,
"type" : "simple",
"inputStage" : {
"stage" : "GEO_NEAR_2DSPHERE",
"keyPattern" : {
"location" : "2dsphere",
"category1" : 1
},
"indexName" : "location_2dsphere_category1_1",
"indexVersion" : 2,
"inputStage" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"location" : "2dsphere",
"category1" : 1
},
"indexName" : "location_2dsphere_category1_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"location" : [ ],
"category1" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"location" : [
"[-9223372036854775807, -6917529027641081857]",
"[-6917529027641081855, -4611686018427387905]",
"[1, 2305843009213693951]",
"[2305843009213693953, 4611686018427387903]",
"[4611686018427387905, 6917529027641081855]",
"[6917529027641081857, 9223372036854775807]"
],
"category1" : [
"[MinKey, MaxKey]"
]
}
}
}
}
},
"rejectedPlans" : [
{
"stage" : "SORT",
"sortPattern" : {
"category2" : 1
},
"memLimit" : 104857600,
"type" : "simple",
"inputStage" : {
"stage" : "GEO_NEAR_2DSPHERE",
"keyPattern" : {
"location" : "2dsphere",
"category2" : 1
},
"indexName" : "location_2dsphere_category2_1",
"indexVersion" : 2,
"inputStage" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"location" : "2dsphere",
"category2" : 1
},
"indexName" : "location_2dsphere_category2_1",
"isMultiKey" : false,
"multiKeyPaths" : {
"location" : [ ],
"category2" : [ ]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"location" : [
"[-9223372036854775807, -6917529027641081857]",
"[-6917529027641081855, -4611686018427387905]",
"[1, 2305843009213693951]",
"[2305843009213693953, 4611686018427387903]",
"[4611686018427387905, 6917529027641081855]",
"[6917529027641081857, 9223372036854775807]"
],
"category2" : [
"[MinKey, MaxKey]"
]
}
}
}
}
}
]
},
"serverInfo" : {
"host" : "XXXX",
"port" : 27017,
"version" : "4.4.1",
"gitVersion" : "ad91a93a5a31e175f5cbf8c69561e788bbc55ce1"
},
"ok" : 1
}
$near是一个范围查询,索引必须在具有范围条件的字段之前引用正在排序的字段,以满足范围和排序要求
这两个索引都不能用于对查询进行排序。MongoDB选择第一个索引,因为它们的可用部分只是地理索引
由于您没有使用$near指定距离,您可能正在通过索引扫描获取设置了位置字段的所有文档。那么我该怎么做呢?我只需要按位置查找并按类别2排序。我尝试了另一种方法创建索引,例如
db.places.createIndex({category2:1,位置:“2dsphere”}
,但随后我得到了错误NoQueryExecutionPlans完整的错误是:``错误:解释失败:{“ok”:0,“errmsg”:“错误处理查询:ns=dev.placesTree:GEONEAR field=location maxdist=1.79769e+308 isNearSphere=0\nsert:{category2:1.0}\nProj:{}”\n planner返回错误::原因::无法找到$geoNear查询的索引,“代码”:291,“代码名”:“NoQueryExecutionPlans”}:``此外,如果由于该错误,我在位置中添加了单个索引,则在执行原始请求时“按位置查找,按类别排序2”“将对位置使用单一索引,忽略复合索引(category2,location)。使用普通索引(而不是2dsphere),则范围索引的工作是预期的,并在您发布的链接中解释。但是2dsphere索引不能作为范围搜索(地理位置搜索)的适当索引。”.有什么线索吗?我想在所描述的查询中使用地理索引后,您将始终处于排序阶段。