Rails 查询具有 has_many 和 belongs_to 关系的模型

Posted

技术标签:

【中文标题】Rails 查询具有 has_many 和 belongs_to 关系的模型【英文标题】:Rails query for models having has_many and belongs_to relationship 【发布时间】:2013-12-24 16:14:01 【问题描述】:

我对 Rails 还很陌生。我有以下型号

class Question < ActiveRecord::Base
  has_many :options
  has_many :response_parts
end

class ResponsePart < ActiveRecord::Base
  belongs_to :question
end

对应的脚手架是

rails g scaffold Question qorder:string qtext:text qtype:string

rails g scaffold ResponsePart answer:string question:belongs_to

现在我想要 qtype 为“移动”的所有响应部分。我尝试了几种方法,但无法成功查询。有人可以告诉一种方法来进行这样的查询。提前致谢。

【问题讨论】:

【参考方案1】:

您可以包含两个模型之间的关系并在其上添加约束:

ResponsePart.includes(:question).where(questions:  qtype: 'mobile' )

这将从数据库中检索所有与“qtype == 'mobile'”匹配的问题的 ResponsePart 对象

这也是检索这些记录的最有效方式。


Question.where(qtype: 'mobile').collect(&:response_parts)

这将查询数据库以获取具有“qtype == 'mobile'”的每个问题的相应 response_parts 示例:如果您有 6 个问题,“qtype == 'mobile'”,它将为每个问题创建 6 个 SQL 查询。

Question.where(qtype: "mobile").first.response_parts

这只是检索与匹配条件“qtype == 'mobile'”的第一个问题相关的 ResponsePart 对象

【讨论】:

谢谢。我得到`#<:relation id: answer: question_id: response_id:>, #]>` 当我查询ResponsePart.includes(:question).where(questions: qtype: 'mobile' ) 时。但现在我想访问相应的答案值。当我使用 'ResponsePart.includes(:question).where(questions: qtype: 'mobile' ).each 并尝试使用 .answer 访问值时,它会给出错误未定义的方法answer。我是否错误地访问了这些值? 嗯,这会涉及另一个问题,但我们可以在这里回答。确保您使用了正确的变量:在您看来,您应该有类似 ResponsePart.includes(:question).where(questions: qtype: 'mobile' ).each do |response_part| 的内容,然后您应该能够通过在 .each 迭代器的块中执行 response_part.answer 来访问答案值 --- 如果您不这样做'不明白这一点,我需要知道你在你的观点中使用的是什么:HAML 或 ERB?那我给你举个例子【参考方案2】:

试试这个

Question.where(qtype: "mobile").first.response_parts

【讨论】:

这不满足要求:它只获取第一个问题的 response_parts,而不是所有问题。 @MrYoshiji 哦,我明白了。是的,你是对的,我误解了这个问题。好渔获【参考方案3】:

试试:

Question.where(qtype: 'mobile').collect(&:response_parts)

这将为您提供所有questionsqtype = 'mobile' 的所有response_parts

更新:(避免 N+1 个查询)

Question.where(qtype: 'mobile').collect(&:response_parts)

这将对每个response_parts 执行一个选择查询,每个question 导致“N+1”个查询。

为了避免“N+1 个查询”,即一个查询来检索问题和 n 查询来检索 resposne_parts,您可以添加 includes(:join_relation)(在您的情况下,:join_relationresponse_parts)作为如下:

Question.includes(:response_parts).where(qtype: 'mobile').collect(&:response_parts)

【讨论】:

这个没有优化,如果qtype == 'mobile'有X个问题,它会生成X个SQL查询来检索它们。 (著名的 N+1 查询:***.com/questions/5452340/…) 感谢@MrYoshiji,我已更新我的答案以解决“N+1”查询问题。

以上是关于Rails 查询具有 has_many 和 belongs_to 关系的模型的主要内容,如果未能解决你的问题,请参考以下文章

带有 has_many belongs_to 关联的 Rails activerecord 查询

Rails:如何通过 has_many 进行优雅的调用

如何在has_many中获取模型的属性:通过Rails 5中的关联

Rails ActiveRecord:三个表 has_many 通过:关联

Rails 关联 has_many 通过禁止/归档解决方案?

用抽象类在Rails中表示has_many关系