如何得到mongoid查询的否定?

时间:2012-01-27 14:44:59

标签: mongodb mongoid

在我的应用中,我有查询:

Model.where(flagged: true, saved: false)

或者我可以使用Model.all(:conditions => {flagged: true, saved: false})

一切都很好。

现在我如何得到该查询的否定?即所有不满足flagged: truesaved: false的模型实例(相当于flagged != truesaved != false

Model.excludes(flagged: true, saved: false)返回满足flagged != truesaved != false)的实例

4 个答案:

答案 0 :(得分:1)

您需要下载到MongoDB rub​​y​​驱动程序才能执行此操作。

如果我正确理解了这个问题,当你在$ ne子句中寻找OR时,Mongoid的exclude命令会执行AND,并且没有方法。

这就是你想要的shell:

find({$or: [{flagged: {$ne: true}}, {saved: {$ne: true}}]})

在ruby中,该查询如下所示:

query = {"$or" => [{"flagged" => {"$ne" => true}}, {"saved" => {"$ne" => true}}]}

如果我没记错,你可以说:

Model.collection.find(query)其中查询是我在上面定义的文档,它应该可以工作。

答案 1 :(得分:0)

您是否尝试过$nor运营商?

Model.all(:conditions => { '$nor' => [ { flagged: true }, { saved: false } ]})

更多信息:http://docs.mongodb.org/manual/reference/operator/query/nor/

答案 2 :(得分:-1)

对于您在问题中使用的特定情况,您可以执行以下操作:

Model.any_of({ flagged: false, saved: true }, { flagged: true, saved: true }, { flagged: false, saved: false } )

但是,正如您在评论中所说,您实际上正在寻找一般解决方案。 AFAIK在Mongoid或MongoDB中无法做到这一点。

原因很可能在于您无法在MongoDB查询中进行连接。例如,用于取消查询的传统SQL方法可能是:

SELECT * FROM mytable t 
WHERE t.id NOT IN ( SELECT t2.id FROM mytable t2 WHERE t2.condition = true )

或者,避免N + 1选择问题

SELECT t.*, t2.id FROM mytable t
OUTER JOIN mytable t2 ON ( t1.id AND t2.condition = true )
WHERE t2.id = NULL

两者都依赖于以某种方式加入两个选择,在Mongo你不能这样做。

唯一的另一种方法是以某种方式反转逻辑,以便得到您特定示例的上述答案。我认为让Mongo自动执行此操作是一个非常糟糕的主意,因为最终会产生代码生成任意复杂的查询,而这些查询无法控制,也无法进行优化。

答案 3 :(得分:-2)

我发现我可以使用Javascript expression syntax

执行此操作

所以否定Model.where(flagged: true, saved: false) - 可以表示为Model.where("this.flagged == true && this.saved == false")

Model.where("!(this.flagged == true && this.saved == false)")

正如Russell的评论所说,这比使用原生查询语言效率低,但对于我的目的来说这不是问题所以我现在正确认为这是正确的 - 但是对于未来的读者请记住性能影响。

如果某人可以给出仅使用本机查询语言的答案,而不进行明确的布尔逻辑扩展,我会将其标记为正确(也许这可能在未来版本的Mongodb / Mongoid中 - 如果可以的话)现在就完成了。)