【发布时间】:2016-08-31 08:39:44
【问题描述】:
我有下一个模型
user.rb
class User < ApplicationRecord
has_many :user_tags, dependent: :destroy
has_many :tags, through: :user_tags
has_many :children, foreign_key: 'parent_id', dependent: :destroy
tag.rb
class Tag < ApplicationRecord
has_many :user_tags, dependent: :destroy
has_many :users, through: :user_tags
user_tag.rb
class UserTag < ApplicationRecord
belongs_to :tag
belongs_to :user
child.rb
class Child < ApplicationRecord
belongs_to :parent, class_name: 'User'
在模型用户中,我有几个范围。
选择用户,与所有必需的标签相关联:
scope :search_by_tags, -> (ids) {
joins(:tags).where(tags: {id: ids}).having('COUNT(tags.id) >= ?', ids.count).group('users.id')
}
其中,生成下一个 SQL 请求
SELECT "users".* FROM "users" INNER JOIN "user_tags" ON "user_tags"."user_id" = "users"."id" INNER JOIN "tags" ON "tags"."id" = "user_tags"."tag_id" WHERE "tags"."id" IN (17, 37, 70, 8, 11, 3, 91, 64) GROUP BY users.id HAVING (COUNT(tags.id) >= 8)
其他范围选择用户,关联特定年龄段的孩子
scope :children_in_ages, -> (age_ranges) {
joins(:children).where(children_ages_query(age_ranges))
.where.not(children: {gender: -1}).group('users.id')
}
def self.children_ages_query(age_ranges)
child_table = Child.arel_table
range_conditions = age_ranges.map { |r| child_table[:birth_date].in(r) }
range_conditions.inject(range_conditions.shift, &:and).to_sql
end
age_ranges 是日期数组。此范围生成下一个 SQL 查询:
SELECT "users".* FROM "users" INNER JOIN "children" ON "children"."parent_id" = "users"."id" WHERE ("children"."birth_date" BETWEEN '2016-02-29 08:35:00.322919' AND '2016-08-31 08:35:00.327283') AND ("children"."gender" != $1) GROUP BY users.id
另外,作用域工作正常,但是当我合并作用域时,我得到了错误的结果。
User.children_in_ages(a).search_by_tags(ids)
User Load (85.2ms) SELECT "users".* FROM "users" INNER JOIN "children" ON "children"."parent_id" = "users"."id" INNER JOIN "user_tags" ON "user_tags"."user_id" = "users"."id" INNER JOIN "tags" ON "tags"."id" = "user_tags"."tag_id" WHERE ("children"."birth_date" BETWEEN '2016-02-29 08:35:00.322919' AND '2016-08-31 08:35:00.327283') AND ("children"."gender" != $1) AND "tags"."id" IN (17, 37, 70, 8, 11, 3, 91, 64) GROUP BY users.id HAVING (COUNT(tags.id) >= 8)
有什么想法可能是错的吗?
【问题讨论】:
-
您并没有真正“合并”范围,而是在其他搜索之上进行“搜索”,通过分析输出 sql 我可以看出它工作得很好。预期的结果是什么——您希望将两个查询的结果合并到一个响应中?
-
@shlajin 例如,
search_by_tags返回 ID 为 [1, 2, 3] 的用户数组,children_in_ages返回 ID 为 [2, 3, 4] 的用户数组。预期结果应该是 ID 为 [2, 3] 的用户数组。所以,是的,我需要两个查询的联合 -
我很难理解你想用
having('COUNT(tags.id) >= ?', ids.count)实现什么,但我不能。search_by_tags方法的目的是什么?这不仅仅是“显示与指定标签相关联的用户”。
标签: sql ruby-on-rails ruby postgresql activerecord