【问题标题】:ActiveRecord 'AND' many to many query, based of array with varying lengthActiveRecord 'AND' 多对多查询,基于不同长度的数组
【发布时间】:2015-10-17 17:03:39
【问题描述】:

我正在开发一个 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 变得更好,我会很乐意使用它。

谢谢!

【问题讨论】:

    标签: ruby-on-rails arrays activerecord


    【解决方案1】:

    试试这个:

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

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

    【讨论】:

    • @PolRod 你觉得这个解决方案有用吗?
    • 抱歉,几天不见!我喜欢这个简单的,但考虑到数组有不同的长度,它似乎不可行!如果它始终具有相同的长度,它将完美地工作。
    • @PolRod 实际上,这适用于不同长度的数组。 [1,2] &amp; [2,3,4] 返回[2]
    • 我明白了。我的意思是,如果选项 id 数组将有 2 个元素,我可以执行上面的示例。但是,如果下次它有 3 个元素,我将不得不添加一个新的&amp; Option.find(array[2]).users。换句话说,似乎必须根据 option_ids 数组的长度硬编码所需的 &amp; Option.find(array[i]).users 数量。
    【解决方案2】:

    您只需使用 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)
    

    【讨论】:

    • 如果我错了,请纠正我,但这里的 expected_users 似乎包含任何已回答 option_ids 上的任何选项的用户。那是对的吗?我需要的是已回答 option_ids 中所有选项的用户列表。因此,已回复 1、2 和 5 的用户不应出现在列表中,但已回复 1、2、3、4 和 5 的用户会出现在列表中。
    猜你喜欢
    • 2018-03-17
    • 1970-01-01
    • 2013-08-21
    • 1970-01-01
    • 1970-01-01
    • 2020-01-17
    • 1970-01-01
    • 2014-05-03
    • 2021-09-28
    相关资源
    最近更新 更多