Есть ли лучший способ SQL сделать этот Array.delete_if в Ruby с помощью запроса Rails.find? - PullRequest
0 голосов
/ 22 августа 2010

У меня есть объект Tag (id, name) и объект Tagging (id, tag_id, type).Я хочу найти все теги, которые имеют имя, например "kevin", и для которых я могу найти иностранный объект Tagging с типом, установленным в "people" (тип может быть установлен в people или какой-либо другой материал для тегирования).

Я пытался выполнить сложный SQL-запрос в методе Rails Tag.find, но не пошел далеко, поэтому сейчас я пытаюсь использовать две строки, используя метод delete_if в Ruby:

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

Это на самом деле работает, но должен быть более разумный способ сделать это непосредственно в базе данных, верно?

Спасибо за вашу помощь,

Кевин

Ответы [ 2 ]

1 голос
/ 22 августа 2010

Попробуйте это:

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

Возвращает теги, начинающиеся с Кевина для type = "person".

Примечание. Параметр group необходим для устранения дубликатов.

1 голос
/ 22 августа 2010

Есть несколько способов улучшить это.

Самым простым улучшением было бы сделать «SELECT count (*)» вместо загрузки 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",
])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...