#ruby-on-rails #activerecord
#ruby-on-rails #activerecord
Вопрос:
У меня есть Filter
объект RelevanceLabels
, с которым связано has_many . RelevanceLabel
Принадлежит an Article
.
Я пытаюсь выполнить уродливый запрос: я хочу найти все Filters
, у которых есть по крайней мере 10 RelevanceLabels
, где у каждого RelevanceLabel
Article
нет a nil
token_vector
.
В настоящее время я использую where_exists
gem, что упрощает первую часть:
streams_with_labels = Filter.where_exists(:relevance_labels)
Но тогда я все еще прибегаю к уродству в циклах:
stream = Filter.find(filter_id)
labels = stream.relevance_labels
return if labels.length < 10
labels_with_tokens = labels.reject { |label| label.article.token_vector.nil? }
return if labels_with_tokens.length < 10
...
Я уверен, что есть какая-то цепочка-фу, которая просто ускользает от меня, но я даже не уверен, с чего начать.
Ответ №1:
То, что вы, вероятно, хотите сделать здесь, это просто СГРУППИРОВАТЬ filters.id
и добавить предложение HAVING, чтобы добавить условие для каждой группы:
class Filter < ApplicationRecord
has_many :relevance_labels
has_many :articles, through: :relevance_labels
def self.with_articles(n = 10)
joins(:articles)
.group(:id) # filters.id
.where.not(articles: { token_vector: nil })
.having(
Article.arel_table[Arel.star].count.gte(n)
)
end
end
Article.arel_table[Arel.star].count.gte(n)
это более переносимый способ записи having("COUNT(articles.*) >= ?", ?)
.