如何获得 mongoid 查询的否定结果?

发布于 2024-12-29 08:30:13 字数 481 浏览 2 评论 0原文

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

Model.where(flaagged: true, saving: false)

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

没问题。

现在我如何得到该查询的否定?即所有不满足 flaged: truesaved: false 的 Model 实例(相当于 flaged!= true OR < code>saved != false)

Model.excludes(flaged: true, saving: false) 返回满足 flaged != true AND 的实例>已保存!= false)

In my app I have the query:

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

Alternatively I can use Model.all(:conditions => {flagged: true, saved: false})

That's all fine.

Now how do I get the negation of that query? i.e. all the instances of Model which do not satisfy flagged: true AND saved: false (which is the equivalent of flagged != true OR saved != false)

Model.excludes(flagged: true, saved: false) returns me the instances which satisfy flagged != true AND saved != false)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

缱倦旧时光 2025-01-05 08:30:13

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

如果我正确理解了这个问题,当您在 $ne 子句之间查找 OR 时,Mongoid 的排除命令会执行 AND 操作,但没有方法可以实现。

这就是您在 shell 中想要的:

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

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

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

如果我没记错的话,您可以说:

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

You need to drop down to the MongoDB ruby driver to do this.

If I'm understanding the question correctly, Mongoid's exclude command does an AND when you are looking for an OR between the $ne clauses and there is no method for it.

This is what you would want in the shell:

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

In ruby, that query looks like this:

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

If I recall correctly you can say:

Model.collection.find(query) where the query is the document i defined above, and it should work.

回梦 2025-01-05 08:30:13

您是否尝试过 $nor 运算符?

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

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

Have you tried $nor operator?

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

More info: http://docs.mongodb.org/manual/reference/operator/query/nor/

命硬 2025-01-05 08:30:13

对于您在问题中使用的具体情况,您可以这样做:

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 自动执行此操作是一个非常糟糕的主意,因为您最终会生成生成任意复杂查询的代码,而您无法控制这些查询,也无法对其进行优化。

For the specific case you use in your question, you can do:

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

However, as you say in your comments, you're actually looking for a general solution. AFAIK there is no way to do this in Mongoid or in MongoDB.

The reason for this most probably lies in the fact that you cannot do joins in a MongoDB query. For example, a traditional SQL way to get a negation of a query might be:

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

Or, to avoid the N+1 selects issue

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

Both of which rely on joining two selects in some way, which in Mongo you can't do.

The only other way is to somehow invert the logic as I do to get the above answer to your specific example. I think it would be a very bad idea to ask Mongo to do this automatically as you would end up with code generating arbitrarily complex queries which you would have no control over and would be unable to optimise.

信愁 2025-01-05 08:30:13

我发现我可以使用 Javascript 表达式语法

因此 Model.where(flaged: true, saving: false) 的否定 - 可以表示为Model.where("this.flaged == true && this.saved == false")

正如

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

Russell 的评论表明这比使用本机查询语言效率较低,但出于我的目的这不是问题,所以我现在将其标记为正确 - 但对于未来的读者,请记住性能影响。

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

I have found I can do this using Javascript expression syntax

So the negation of Model.where(flagged: true, saved: false) - which can be expressed as Model.where("this.flagged == true && this.saved == false")

is

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

As Russell's comment suggests this is less efficient than using the native query language, but for my purposes that is not a problem so I am marking this correct for now - but for future readers bear in mind the performance implications.

If someone can give an answer that uses only the native query language, without doing an explicit boolean logic expansion, I'll mark that correct (maybe that will be possible in a future version of Mongodb/Mongoid - if it can't be done now.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文