我有大约1M的文档或多或少像这样:
{
"_id" : ObjectId("5461c8f0426f727f16000000")
"ec" : 9,
"ai" : 9390448,
"f" : [
{
"t" : "ry",
"v" : 1994
},
{
"t" : "g",
"v" : [
"Crime",
"Drama"
]
},
{
"t" : "ml",
"v" : "English"
},
{
"t" : "k",
"v" : "movie"
},
{
"t" : "rel",
"v" : true
}
]
}
我有必要进行这样的查询:
db.items.find(
{
$and:[
{f:{$elemMatch:{t:"ml", v:{$in:["English", "Spanish", "French", "German"]}}}},
{f:{$elemMatch:{t:"rel", v:true}}},
{f:{$elemMatch:{t:"k", v:"movie"}}},
{f:{$elemMatch:{t:"ry", v:{$gte:1980}}}},
{f:{$elemMatch:{t:"g", v:{$in:["Thriller"]}}}},
]
}).sort({ai: -1}).limit(12)
就像这样:
db.items.find(
{
$and:[
{f:{$elemMatch:{t:"ml", v:{$in:["English", "Spanish", "French", "German"]}}}},
{f:{$elemMatch:{t:"rel", v:true}}},
{f:{$elemMatch:{t:"k", v:"movie"}}},
{f:{$elemMatch:{t:"ry", v:{$gte:1980}}}},
{f:{$elemMatch:{t:"g", v:{$in:["Thriller"]}}}},
]
}).sort({ec: -1}).limit(12)
注意排序差异。
我创建了以下索引:
{
"f.t" : 1,
"f.v" : 1,
"ec" : -1,
"ai" : -1
}
因此,我认为我可以查询包括ec
。即使我只想与ai
进行排序,我也可以介绍{ec: {$gte: 0}}
(ec
对所有文档的值为0或更大。)
如果我进行以下查询,它会使用索引,一切正常:
db.items.find(
{
$and:[
{f:{$elemMatch:{t:"ml", v:{$in:["English", "Spanish", "French", "German"]}}}},
{f:{$elemMatch:{t:"rel", v:true}}},
{f:{$elemMatch:{t:"k", v:"movie"}}},
{f:{$elemMatch:{t:"ry", v:{$gte:1980}}}},
{f:{$elemMatch:{t:"g", v:{$in:["Thriller"]}}}},
{ec: {$gte: 0}}
]
}).limit(12)
但是,当我使用ai
引入排序时,它变得非常慢并且“从不”回来:
db.items.find(
{
$and:[
{f:{$elemMatch:{t:"ml", v:{$in:["English", "Spanish", "French", "German"]}}}},
{f:{$elemMatch:{t:"rel", v:true}}},
{f:{$elemMatch:{t:"k", v:"movie"}}},
{f:{$elemMatch:{t:"ry", v:{$gte:1980}}}},
{f:{$elemMatch:{t:"g", v:{$in:["Thriller"]}}}},
{ec: {$gte: 0}}
]
}).sort({ai: -1}).limit(12)
我不太明白这种行为。我猜测唯一的方法是为此创建两个不同的索引。
想法?
感谢。
答案 0 :(得分:1)
索引可以支持对索引键模式的非前缀子集进行排序操作。为此,查询必须在排序键之前的所有前缀键上包含相等条件。
AFAIK,$gte
并不算作平等条件;只有{ <field>: <value> }
。
使用多个索引可以解决您的问题:
{ "f.t" : 1, "f.v" : 1, "ec" : -1 }
{ "ai" : -1 }
(未测试的)