我试图尽可能地优化DB查找。据我了解,我的目标应该是针对唯一阶段的获胜计划。但是我有一个包含日期密钥的字段,似乎我无法构建一个化合物索引,该复合索引在过滤" null"日期值时可以直接查找。
我的过滤器查询是以下
{"$and":[
{"published":true},
{"soft_deleted_at":null}, # <-- this one's a date field, I need null values
{"another_filter":false},
{"yet_another_filter":false}
]}`
我尝试建立一个与此查询完全对应的部分索引(为了节省一些索引内存,因为我知道我永远不必显示以下删除的文档)
(请注意代码在Ruby中
index(
{
published: 1,
another_filter: 1,
soft_deleted_at: 1,
yet_another_filter: 1,
},
{
background: true,
name: 'Visible in search engine partial index',
partial_filter_expression: {
'$and': [
{"published":true},
{"soft_deleted_at":null},
{"another_filter":false},
{"yet_another_filter":false}
]
}
}
)
除了soft_deleted_at
过滤器外,这似乎很好,因为我的获胜计划看起来像
=> {"stage"=>"FETCH",
"filter"=>{"soft_deleted_at"=>{"$eq"=>nil}},
"inputStage"=>
{"stage"=>"IXSCAN",
"keyPattern"=>{"published"=>1, "another_filter"=>1, "soft_deleted_at"=>1, "yet_another_filter"=>1},
"indexName"=>"Visible in search engine partial index",
"isMultiKey"=>false,
"multiKeyPaths"=>{"published"=>[], "another_filter"=>[], "soft_deleted_at"=>[], "yet_another_filter"=>[]},
"isUnique"=>false,
"isSparse"=>false,
"isPartial"=>true,
"indexVersion"=>2,
"direction"=>"forward",
"indexBounds"=>
{"published"=>["[true, true]"], "another_filter"=>["[false, false]"], "soft_deleted_at"=>["[null, null]"], "yet_another_filter"=>["[false, false]"]}}}
因此,在这里,我有这个额外的阶段"stage"=>"FETCH", "filter"=>{"soft_deleted_at"=>{"$eq"=>nil}},
,基本上是在手动过滤我的日期字段fr null值。我希望这已经在部分索引中,不需要更多的过滤...我错了吗?
有某种方法可以避免此额外的过滤阶段吗?
有什么方法可以避免此额外的过滤阶段?
不,没有。(至少不是您当前的数据模式)
mongo为不存在的索引(null&amp; Undefined)与存在略有不同。它实际上是在使用soft_deleted_at
索引(请注意,它在[null, null]
范围内进行过滤,但这也是soft_deleted_at
为undefined
的值,它无法使用该索引来过滤这些值,因此它必须执行filter
步骤。
通常,最好避免过滤阶段,但这似乎不是昂贵的情况。您不会获取任何额外的文件,因此唯一的成本是检查单个字段的获取文档。
替代方案是添加像false
之类的值并搜索。如果您有像deleted
这样的字段,则每个文档对每个文档(并且与soft_deleted_at
同时更新),您的查询计划将不包括filter
阶段。