我在这里有两种方法,distinct_question_ids 和 @correct_on_first 尝试。目标是向用户展示有多少不同的多项选择题已被正确回答。

第二个将让我知道在第一次尝试中正确回答了多少这些不同的 MCQ。 (用户可以多次尝试 MCQ)

现在,当用户回答数千个问题并有数千个用户答案时,显示其性能的页面需要 30 秒到 1 分钟才能加载。我相信这是由于 .select 方法,但我不知道如何在不使用 .select 的情况下替换 .select,因为它就像 .each 一样循环

有没有什么方法不会导致N+1?

distinct_question_ids = @user.user_answers.includes(:multiple_choice_question).
  where(is_correct_answer: true).
  distinct.pluck(:multiple_choice_question_id)

@correct_on_first_attempt = distinct_question_ids.select { |qid|
  @user.user_answers.
    where(multiple_choice_question_id: qid).first.is_correct_answer
}.count

最佳答案

.pluck 返回值数组,而不是 ActiveRecord::Relation。

因此,当您执行 distinct_question_ids.select 时,您不是在调用 ActiveRecord 的 select ,而是调用 Array 的 select 。在该选择中,您将针对您刚刚选择的每个 id 对 @user 发出一个全新的查询——包括在选择中被拒绝的那些。

您可以创建一个名为 distinct_questions 的查询,该查询返回一个关系(没有勇气!),然后从中构建 correct_on_first_attempt,我认为您将避免 N+1 查询。

沿着这些路线的东西:

class UserAnswer < ActiveRecord::Base
   scope :distinct_correct, -> { includes(:multiple_choice_question)
                                   .where(is_correct_answer: true).distinct }

   scope :first_attempt_correct, -> { distinct_correct
                                        .first.is_correct_answer }
end

class User < ActiveRecord::Base
  def good_guess_count
    @correct_on_first_attempt = @user.user_answers.distinct_correct.first_attempt_correct.count
  end
end

您需要确保 .first 实际上是第一次尝试,可能是通过按 id 或 created_at 排序。

顺便说一句,如果您在 UserAnswer 中明确跟踪尝试次数,您可以真正加强这一点:
class UserAnswer < ActiveRecord::Base
  scope :correct, -> { where(is_correct_answer: true) }
  scope :first_attempt, -> { where(attempt: 1) }
end

class User < ActiveRecord::Base
  def lucky_guess_count
    @correct_on_first_attempt = @user.user_answers.includes(:multiple_choice_question)
                                     .correct.first_attempt.count
  end
end

如果您的架构中没有尝试次数,您可以使用 .order 和 .group 来获得类似的东西。但是...似乎您的某些项目要求取决于该序列号,因此如果您还没有它,我建议您添加它。

附:对于 N+1 查询,请使用 gem bullet。这是在点。

关于ruby-on-rails - .select 和或 .where 是否负责导致 Rails 中的 N+1 个查询?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54499631/

10-16 12:56
查看更多