是否有更好的SQL方法来使用Rails.find请求执行此Ruby的Array.delete_if?

时间:2010-08-21 21:32:22

标签: sql ruby-on-rails ruby

我有一个Tag对象(id,name)和一个Tagging对象(id,tag_id,type)。我想找到所有名称都像“kevin”的标签,我可以找到一个外部Tagging对象,类型设置为“people”(类型可以设置为人或其他标记内容)。

我尝试在Rails Tag.find方法中使用复杂的SQL请求,但没有走得太远,所以我现在尝试使用Ruby的delete_if方法使用两行:

people = Tag.find(:all, :conditions => ["name like ?", "Kevin%"])
people.delete_if { |p| Tagging.find(:all, :conditions => { :tag_id => p.id, :type => "people" }).empty? }

它确实有效,但必须有一种更聪明的方法直接在数据库中执行此操作,对吧?

感谢您的帮助,

凯文

2 个答案:

答案 0 :(得分:1)

有几种方法可以改进。

最简单的改进是执行“SELECT count(*)”而不是为那些Taggings加载ActiveRecords。

people = Tag.all(:conditions => ["name LIKE ?", "Kevin%"])
people.delete_if { |p| Tagging.count(:conditions => { :tag_id => p.id, :type => "people" }) > 0 }

但是整个事情也可以在带有子查询的SQL中完成:

people = Tag.all(:conditions => [
     "name LIKE ? AND id IN (SELECT tag_id FROM people WHERE type=?)", 
     "Kevin%",
     "people",
])

答案 1 :(得分:1)

试试这个:

Tag.all(:joins => :taggings, :group => :id, 
        :conditions => ["tags.name LIKE ? AND taggings.type = ?", 
                         "Kevin%", "person"]
)

返回以Kevin开头的标签为type =“person”。

注意:需要使用group选项来消除重复项。