在Ruby on Rails中,似乎有两种方法可以检查集合中是否包含任何元素。
即,它们是ActiveRecord::FinderMethods’ exists?和ActiveRecord::Relation’s any?。在通用查询(Foo.first.bars.exists?
和Foo.first.bars.any?
)中运行这些生成的等效SQL。有没有理由使用其中一个?
答案 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?
中工作,如果你没有通过,那么无论如何都将转换你在数组中使用的关系一个街区。