Sql 将activerecord查询的循环减少为一个查询

Sql 将activerecord查询的循环减少为一个查询,sql,ruby-on-rails,activerecord,Sql,Ruby On Rails,Activerecord,我有一个列表模型,它有一个category列和size列。对于每个类别,我都有一个大小数组。我只想返回每个类别中与大小数组相对应的列表。(我还有一个设计器数组作为params[:designer]的条件。) 参数散列: params[:category] => ['tops', 'bottoms', 'outerwear', 'footwear'] params['tops'] => ['M', 'L'] params['bottoms'] => [] params['oute

我有一个列表模型,它有一个category列和size列。对于每个类别,我都有一个大小数组。我只想返回每个类别中与大小数组相对应的列表。(我还有一个设计器数组作为params[:designer]的条件。)

参数散列:

params[:category] => ['tops', 'bottoms', 'outerwear', 'footwear']
params['tops'] => ['M', 'L']
params['bottoms'] => []
params['outerwear'] => ['XL']
params['footwear'] => ['11', '12']
我已经创建了一个循环来执行此操作:

@listings = []
params[:category].each do |category|
  @listings += Listing.where(category: category, size: params[category], designer: params[:designer], sold: nil).includes(:photos).page(params[:category_page]).per(@perpage)
end

但我需要将其全部放在一个查询中,因为我正在使用kaminari gem(即.page调用)对其进行分页。

将其转换为in查询:

Listing.where(designer: params[:designer]).where("category IN (?)", params[:category])
更新:

似乎上面的代码不是op想要的,所以我做了一些修改。如果我理解正确,您需要生成一个包含大量ORs的大查询。你不用去阿雷尔也可以做到:

params[:category] = ['tops', 'bottoms', 'outerwear', 'footwear']
params['tops'] = ['M', 'L']
params['bottoms'] = []
params['outerwear'] = ['XL']
params['footwear'] = ['11', '12']

query = params[:category].map do |category|
  str = "(category = ?"
  str += " AND size IN (?)" if params[category].any?
  str += ")"
  str
end

scope = Listing.where(query.join(" OR "), *params[:category].map { |cat| [cat, params[cat].any? ? params[cat] : nil] }.flatten(1).compact)
scope = scope.where(designer: params[:designer], sold: nil)
scope = scope.page(params[:per_page]).per(@page)
它生成此查询(分页前):


您可以将数组传递到
,其中

@listings = Listing.where(category: params[:category], s...

我最后用了阿雷尔,这很不错。Arel允许您建立任何您想要的查询,然后在Model.where()上调用它。这有点复杂,但这是我发现唯一有效的解决方案

t = Listing.arel_table
query = t[:category].eq('rooney')
params[:category].each do |category|
  if params[category]
    params[category].each do |size|
      query = query.or(t[:category].eq(category).and(t[:size].eq(size)))
    end
  end
end
dquery = t[:designer].eq('rooney')
params[:designer].each do |designer|
  dquery = dquery.or(t[:designer].eq(designer))
end
query = query.and(dquery)
@listings = Listing.where(query).includes(:photos).page(params[:category_page]).per(@perpage)
编辑:

可以使用.eq_any()简化设计器查询


我可能遗漏了一些东西,但我不认为这是在不同类别中找到不同大小的地址。我可能遗漏了一些东西,但我不认为这是在不同类别中找到不同大小的地址。
t = Listing.arel_table
query = t[:category].eq('rooney')
params[:category].each do |category|
  if params[category]
    params[category].each do |size|
      query = query.or(t[:category].eq(category).and(t[:size].eq(size)))
    end
  end
end
dquery = t[:designer].eq('rooney')
params[:designer].each do |designer|
  dquery = dquery.or(t[:designer].eq(designer))
end
query = query.and(dquery)
@listings = Listing.where(query).includes(:photos).page(params[:category_page]).per(@perpage)
t = Listing.arel_table
query = t[:category].eq('rooney')
params[:category].each do |category|
  if params[category]
    params[category].each do |size|
      query = query.or(t[:category].eq(category).and(t[:size].eq(size)))
    end
  end
end
dquery = t[:designer].eq_any(params[:designer])
query = query.and(dquery)
@listings = Listing.where(query).includes(:photos).page(params[:category_page]).per(@perpage)