Ruby on Rails中`any?`和`exists?`之间的区别?

时间:2018-01-19 22:32:27

标签: ruby-on-rails ruby ruby-on-rails-4 activerecord

在Ruby on Rails中,似乎有两种方法可以检查集合中是否包含任何元素。

即,它们是ActiveRecord::FinderMethods’ exists?ActiveRecord::Relation’s any?。在通用查询(Foo.first.bars.exists?Foo.first.bars.any?)中运行这些生成的等效SQL。有没有理由使用其中一个?

2 个答案:

答案 0 :(得分:2)

#any#exists?是非常不同的野兽,但查询类似。

主要是,#any?接受一个块 - 并使用此块检索关系中的记录,调用#to_a,调用块,然后使用Enumerable#any?命中它。没有块,它等同于!empty?并计算关系的记录。

#exists? 总是查询数据库并且永​​远不会依赖于预加载的记录,并设置LIMIT为1.它与#any?相比性能更高。 #exists?还接受选项参数作为应用条件,如您在文档中所见。

答案 1 :(得分:1)

ActiveRecord#any?的使用量减少了ActiveRecord#exists?。有没有?在传递块的情况下,您可以检查该数组中的某些元素是否与条件匹配。与Enumerable#any?类似,但不要混淆它们。

ActiveRecord#any?在其definition的逻辑内部实现Enumerable#any?,通过将访问的Relation转换为数组,以防块传递给它并生成并访问块用“手工制作”方式实现“Ruby”any?方法的参数。

其他方便的补充意在回归空虚的否定?适用于关系。这就是为什么你可以检查模型是否有或没有记录,如:

User.count # 0
User.any?  # false
# SELECT  1 AS one FROM "users" LIMIT ?  [["LIMIT", 1]]
User.exists? # false
# SELECT  1 AS one FROM "users" LIMIT ?  [["LIMIT", 1]]

您还可以查看“任何?”如果某些记录属性具有特定值:

Foo.any? { |foo| foo.title == 'foo' } # SELECT "posts".* FROM "posts"

或者通过使用存在来节省“效率”?并改进您的查询和代码行:

Foo.exists?('foo') # SELECT  1 AS one FROM "posts" WHERE "posts"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]

ActiveRecord#exists?提供了许多实现,并且打算在SQL级别而不是any?中工作,如果你没有通过,那么无论如何都将转换你在数组中使用的关系一个街区。