假设我有一个 struct 如下的文档:
_id: ObjectId,
user_id: int,
deleted: bool,
'additional.id': string, // optional field
synced_at: Date //optional field
示例文档将是:
{
"_id" : ObjectId("5dce551d6ad5bb1fd829bd77"),
"user_id" : NumberInt(1),
"additional" : {
"id" : "hahahah"
},
"deleted" : false,
"synced_at" : ISODate("2023-12-19T19:21:26.678+0000")
}
我需要获取与此查询匹配的所有文档的计数:
aggregate(
[
{
$match: {
user_id: 1,
deleted: false,
"additional.id" : {$exists : true},
synced_at : {
$gte: new Date(new Date() - 7 * 60 * 60 * 24 * 1000)
},
}
}
,
{
$count : "productsCount"
}
]
)
所以我创建了一个这样的索引:
createIndex(
{
"user_id": 1,
"deleted": 1,
"additional.id": 1,
"synced_at": -1,
},
{
partialFilterExpression: {
"deleted" : false,
"additional.id" : {
"$exists" : true
},
"synced_at" : {
"$exists" : true
}
}
)
假设查询结果为20000.当我运行一个带有.explain("executionStats")
的查询时,我可以看到totalKeysExamined
和totalDocsExamined
都等于20000,如果我没有弄错的话,这意味着从索引中提取了20k个产品,此外,mongo还在所有这20k个产品上进行了查找.更深入地查看执行统计数据,我可以看到索引的顶部有Fetch
个阶段:
"executionStages" : {
"stage" : "FETCH",
"filter" : {
"$and" : [
{
"additiona.id" : {
"$exists" : true
}
,
]
},
所以,如果我没有弄错的话,这意味着Mongo从索引中获取了所有需要的文档(20k),但出于某种原因,还额外判断了20k产品中的每一个,如果是 "additiona.id" : {"$exists" : true}
,即使它已经在partialFilterExpression
中
我能以某种方式避开这个诱人的阶段吗?我在Mongo 5频道.