ActiveRecord'AND'基于具有不同长度的数组进行多对多查询

时间:2015-10-17 17:03:40

标签: ruby-on-rails arrays activerecord

我正在开发一个Rails应用程序。我有一个option_id的数组,它可以有不同的长度。通过答案,选项和用户之间存在多对多的关系。鉴于以下模型:

class Option < ActiveRecord::Base
  has_many :answers
  has_many :users, through: :answers
end

class User < ActiveRecord::Base
  has_many :answers
  has_many :options, through: :answers
end

class Answer < ActiveRecord::Base
  belongs_to :user
  belongs_to :option
end

我必须找到已回答数组中所有选项的所有用户。 例如,如果数组是[1,2],我希望由Option.find(1).usersOption.find(2).users返回的用户的交集。在这种情况下,我认为这可以通过Option.find(1).users.merge(Option.find(2).users)这样的方式来实现。 但是,阵列可能包含任意数量的元素,使上述解决方案不可行。

我唯一的想法是执行如下所示的循环,但对于较长的数组,这似乎真的是数据库调用很重:

array = [1,2,3,4,5]
array.each do |option_id, index|
 if index == 0
       users = Option.find(option_id).users
 end
 users = users.merge(Option.find(option_id).users)
end

我想知道是否会有一种更优雅,更简单的方法来获取单个查询中的信息和/或不依赖于循环。如果它做得更好,我很乐意使用SQL。

谢谢!

2 个答案:

答案 0 :(得分:0)

试试这个:

Option.find(1).users & Option.find(2).users

&是类Array的Ruby方法,它将返回任意长度的2个数组的交集。

答案 1 :(得分:0)

您可以通过以下方式使用 2个SQL查询 (无论option_ids数组的长度)来实现您的目标:

option_ids = [1, 2, 3, 4, 5]

# select all the user_id's from the answers table (by joining options and answers tables) 
# based on the option_ids array (1 SQL Query)
user_ids = Option.joins(:answers)
                 .where('answers.option_id IN (?)', option_ids)
                 .select('answers.user_id')

# get the users from the users table (1 SQL Query)  
expected_users = User.find(user_ids)