【问题标题】:Rails have activerecord grab all needed associations in one go?Rails 有 activerecord 一口气抓取所有需要的关联吗?
【发布时间】:2012-01-04 05:58:44
【问题描述】:

我有一个模型评论,它有一个用户。

在我的显示页面中,我正在做一个Comment.all,然后显示每个评论。

在视图中,我不仅需要显示评论,还需要显示相关用户(即作者)的信息。

<% @comments.each do |comment| %>
    <%= comment.user.name %>
    <%= comment.user.email %>
    ...etc...
<% end %>

这很好,但是根据我的每条评论,activerecord 会将其转换为一个SELECT * FROM users WHERE USER.id = commentId 查询。

这有点荒谬,尤其是在有数百个 cmets 的页面上。 (这是数百个单独的独立数据库命中!)

当我在执行 Comment.all 时,是否可以告诉 rails 不仅要抓取 cmets,还要抓取关联的用户,然后当我稍后调用 comment.user.blah 时,让它不抓取它再次从分贝? (这样它就可以在一个 db 语句中完成所有操作)。

【问题讨论】:

    标签: sql ruby-on-rails postgresql activerecord


    【解决方案1】:

    你应该使用.includes

    来自doc

    N+1查询问题的解决方案

    Active Record 允许您预先指定所有将要加载的关联。这可以通过指定 Model.find 调用的 include 方法来实现。通过包含,Active Record 可确保使用尽可能少的查询来加载所有指定的关联。

    重新审视上述案例,我们可以重写 Client.all 以使用急切加载地址:

    clients = Client.includes(:address).limit(10)
    
    clients.each do |client|
      puts client.address.postcode
    end
    

    或者,在你的情况下,它会是

    Comment.includes(:user)
    

    【讨论】:

      【解决方案2】:

      您可以使用 ActiveRecord 轻松完成此操作,您只需要使用其中的 eager loading 功能即可。所以Comment.all(:include =&gt; :user) 将运行一个大型查询,而不是每条记录一个查询。

      【讨论】:

        【解决方案3】:

        如果您想在includes 语句中与多个关联关联,请查看http://stackoverflow.com/questions/29908230/rails-have-activerecord-grab-more-than-one-association-in-one-go/29908317#29908317

        要点是使用Comment.includes(:user, :dates, :whatevertableetc)

        【讨论】:

          猜你喜欢
          • 2015-07-06
          • 1970-01-01
          • 2018-05-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-17
          • 1970-01-01
          相关资源
          最近更新 更多