这个问题是Query with $in and $nin doesn't use index的后续问题。我已经尝试使用聚合来声明步骤的顺序。
db.assets.aggregate([
{
"$match": {
"tags": {
"$in": ["blah"]
}
}
},
{
"$match": {
"tags": {
"$nin": ["test"]
}
}
}
], {"explain": true})
你认为Mongo现在明白我们想先用$过滤。好吧,你会感到惊讶。
{
"stages" : [
{
"$cursor" : {
"query" : {
"$and" : [
{
"tags" : {
"$in" : [
"blah"
]
}
},
{
"tags" : {
"$nin" : [
"test"
]
}
}
]
},
"planError" : "InternalError No plan available to provide stats"
}
}
],
"ok" : 1
}
规划师甚至不知道该怎么做。事实证明它实际上将$match
es组合成一个查询,然后遇到与Query with $in and $nin doesn't use index相同的问题,最终在大约2-3秒内返回结果(对应于链接上的2331ms)问题)。
答案 0 :(得分:0)
看起来你可以通过插入一个空的跳过步骤来欺骗聚合器:
db.assets.aggregate([
{
"$match": {
"tags": {
"$in": ["blah"]
}
}
},
{
"$skip": 0
},
{
"$match": {
"tags": {
"$nin": ["test"]
}
}
}
], {"explain": true})
这样,计划者将使用索引并立即返回结果。
{
"stages" : [
{
"$cursor" : {
"query" : {
"tags" : {
"$in" : [
"blah"
]
}
},
"plan" : {
"cursor" : "BtreeCursor ",
"isMultiKey" : false,
"scanAndOrder" : false,
"indexBounds" : {
"tags" : [
[ "blah", "blah" ]
]
},
"allPlans" : [
{
"cursor" : "BtreeCursor ",
"isMultiKey" : false,
"scanAndOrder" : false,
"indexBounds" : {
"tags" : [
[ "blah", "blah" ]
]
}
}
]
}
}
},
{
"$skip" : NumberLong(0)
},
{
"$match" : {
"tags" : {
"$nin" : [
"test"
]
}
}
}
],
"ok" : 1
}