Rails ActiveRecord与has_many关联相交查询

时间:2015-11-06 00:24:12

标签: ruby-on-rails ruby activerecord

我有以下型号:

class Piece < ActiveRecord::Base
     has_many :instrument_pieces
     has_many :instruments, through: :instrument_pieces
end

class Instrument < ActiveRecord::Base
    has_many :pieces, through: :instrument_pieces
    has_many :instrument_pieces
end

class InstrumentPiece < ActiveRecord::Base
    belongs_to :instrument 
    belongs_to :piece
end

我有以下问题:

Piece
.joins(:instrument_pieces)   
.where(instrument_pieces: { instrument_id: search_params[:instruments] } )
.find_each(batch_size: 20) do |p|

search_params[:instruments]是一个数组。此查询的问题在于它将检索具有任何工具的所有部分,因此如果search_params[:instruments] = ["1","3"],查询将返回具有1或3或两者的工具关联的部分。我希望查询只返回其乐器关联包括乐器1和3的乐曲。我已经阅读了文档,但我仍然不确定如何做到这一点...... < / p>

2 个答案:

答案 0 :(得分:2)

似乎我想要的是两个查询之间的交集,所以我最终做的是:

queries = []
query = Piece.joins(:instruments)   
search_params[:instruments].each do |instrument|
    queries << query.where(instruments: {id: instrument})
end
sql_str = ""
queries.each_with_index do |query, i|
    sql_str += "#{query.to_sql}"
    sql_str += " INTERSECT " if i != queries.length - 1
end

Piece.find_by_sql(sql_str).each do |p|

非常难看,但ActiveRecord还不支持INTERSECT。我想是等待ActiveRecord 5的时候了。

答案 1 :(得分:1)

您可以使用where子句链接来实现此目的。尝试:

query = Piece.joins(:instrument_pieces)   
search_params[:instruments].each do |instrument|
  query = query.where(instrument_pieces: { instrument_id: instrument } )
end
query.find_each(batch_size: 20) do |p|

或其他版本

query = Piece.joins(:instruments)   
search_params[:instruments].each do |instrument|
  query = query.where(instrument_id: instrument)
end
query.find_each(batch_size: 20) do |p|