我正在开发一种软件,可以将业务领域中的查询转换为MongoDB查询文档。
对于这一点,我需要一些像'" WHERE 0 == 1" MongoDB的子句,即可以与$and
和$or
运算符组合在一起的查询文档,其行为类似于逻辑false
,可以通过mongo查询引擎进行优化。
这样,如果查询构建器的某个子部分检测到"不可能"条件,它可以返回这个" false"查询文档,让mongodb引擎忽略查询语法树的相应分支。
{$where: "false"}
可以解决这个问题,但似乎在这种情况下,mongoDB引擎会评估" false"在结果的每一行(而不是简单地返回一个空的结果集)。
我也提出{_id: {$exists: false}}
,但explain()
显示查询仍然使用索引扫描。
所以我很好奇是否有任何其他选项可以获得空结果集。
更深入的解释
我的软件用户将能够以特定于域的查询语言定义查询,该语言将被翻译成相当复杂的mongodb查询文档。此查询基本上具有{$and: [ {$or: [ {},{$and: ...},...]}]}
的形式,因此这是一个深度嵌套,相当复杂的条件树。
树的构造目前很简单,因为域查询的每个元素或多或少都会很好地转换为相应的Mongo查询。
如果在我的软件可以自行决定的树的深处有一个条件,它始终是假的,我想尽可能明确地将它设置为Mongo查询引擎。例如,如果所有"中间"文档由$and
个运算符组成(因此查询的总结果总是" false"),我希望mongo引擎能够尽快检测到它。
如果我在SQL中执行此操作,则等效项将类似于
SELECT * FROM TABLE WHERE C1 AND C2 AND (C3 OR C4) AND ... AND (1=0)
当SQL引擎获得此查询时,它根本不需要查阅任何索引或表,因为条件可以被证明"总是假的。
答案 0 :(得分:0)
索引扫描将是您在解释查询中看到的最快的操作之一。使其更快的一个选择是创建稀疏索引,然后强制您的查询使用提示来使用该索引。
索引创建:
db.myCollection.createIndex( { "does_not_exist": 1 }, { sparse: true })
查询:
db.myCollection.find(
{ "does_not_exist":
{ $exists: true },
$hint:
{does_not_exist : 1}
})
我自己没有测试过,所以你可能需要自己测试一下,看看这是否适合你的需要,但我怀疑这是一条值得探索的道路。
答案 1 :(得分:0)
首先,您应该只使用$where
运算符,并且只有在您使用任何其他查询运算符无法解决问题时才使用。但是根据我的经验,如果$where
能够做到这一点,那么$redact
会做得更好,除非你的架构设计非常糟糕,或者你的查询表达式中不应该做些什么。
在此post中,我解释了为什么应该使用$redact
代替$where
。
根据我的理解,您可以使用$redact
运算符执行此操作:
db.collection.aggregate([
{ "$redact": {
"$cond": [
{ "$eq": [true, false]},
"$$KEEP",
"$$PRUNE"
]
}}
])
$$KEEP
和$$PRUNE
变量是一个系统变量,允许您根据{{3}的重新调整的值“保留”或排除所有文档} itional expression。
答案 2 :(得分:0)
在3.6版中,您可以直接表达以下内容:
{ $expr: { $eq: [0, 1] } }