【问题标题】:Rails + SQL: Eager load 2 models with a SQL query involving 3 tables?Rails + SQL:使用涉及 3 个表的 SQL 查询急切加载 2 个模型?
【发布时间】:2014-12-05 06:55:40
【问题描述】:

大纲

按节目最后修改日期降序显示用户节目/剧集的信息。

模型/关系

User
    has_many :shows

Show
    has_many :episodes
    belongs_to :user

Episode
    belongs_to :show

我的尝试

@shows = Show.find_by_sql("SELECT * FROM Shows join Episodes on Episodes.id = Shows.episode_id 和 Episodes.user_id = '#{current_user.id}' ORDER BY shows.updated_at DESC")

问题

我的 SQL 查询以适当的顺序加载用户的节目,但它并不急切地加载适当的剧集——导致 N+1 问题。

如何构造一个查询来预先加载我需要的节目和剧集的所有信息?

【问题讨论】:

    标签: sql ruby-on-rails


    【解决方案1】:

    首先:不要使用find_by_sql。如果您正在使用它,您将不得不处理此类问题,而 ActiveRecord 帮不了您。

    试试这个:

    @shows = current_user.shows.preload(:episodes)
    

    这将导致 2 个查询,一个针对 current_user 的节目,另一个针对所有剧集。另一种选择是:

    @shows = current_user.shows.joins(:episodes)
    

    这将通过单个查询加载所有内容。我个人更喜欢preload,因为它更符合语义,有时,对于更复杂的查询,joins 可能会破坏您的查询。

    顺便说一句:如果你想预加载另一个关系,这可以很容易地完成。像这样:

    @shows = current_user.shows.preload(:host, :episodes => :author)
    

    【讨论】:

    • 谢谢,我会接受你的回答。我最终使用了:@shows = Show.eager_load(:episode).where("shows.id IN (select shows.id from shows join episodes on episodes.id = shows.episode_id 和 episode.user_id = ? ORDER BY 节目。 updated_at DESC)", current_user.id) 。我愿意接受关于我的查询的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-27
    • 1970-01-01
    • 2013-03-14
    相关资源
    最近更新 更多