【问题标题】:Complex :includes for Eager Loading复杂 :includes 用于急切加载
【发布时间】:2013-08-24 14:35:48
【问题描述】:

我正在尝试创建一个非常复杂的急切负载;我想修改第二个语句,而不是第一个。我需要在第二个语句上创建一个连接,其中包含另一个表中的列。

我尝试的所有内容都会修改第一条语句,而第二条则保持原样。如果有另一种方法可以在没有 N+1 查询的情况下完成相同的任务,我愿意。

这个:

Conversation.joins(:phones)
            .where('phones.id' => 2)
            .order('last_message_at DESC')
            .includes(:messages)

生成:

SELECT "conversations".* FROM "conversations" 
 INNER JOIN "conversations_phones" 
  ON "conversations_phones"."conversation_id" = "conversations"."id" 
 INNER JOIN "phones"
  ON "phones"."id" = "conversations_phones"."phone_id" 
 WHERE "phones"."id" = 2 ORDER BY last_message_at DESC

SELECT "messages".* FROM "messages" 
 WHERE "messages"."conversation_id" IN (10, 11) ORDER BY created_at ASC

有道理,但不是我想去的地方。

我可以用这样的方式编写所需的第二条语句:

Message.joins(:message_tags)
       .select('messages.*, message_tags.status as read')
       .group('messages.id, message_tags.status')
       .order('messages.id')
       .where(:message_tags => { :user_id => current_user.id })
       .where(:messages => { :conversation_id => [10, 11] })

正确生成:

SELECT messages.*, message_tags.status as read FROM "messages" 
 INNER JOIN "message_tags" ON "message_tags"."message_id" = "messages"."id" 
 WHERE "message_tags"."user_id" = 2 AND "messages"."conversation_id" IN (10, 11) 
 GROUP BY messages.id, message_tags.status 
 ORDER BY messages.id

基本上,我希望选择更复杂的消息来替换更简单的消息,这样我就可以在不创建新查询的情况下调用@conversations.first.messages.first.read。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 eager-loading


    【解决方案1】:

    听起来你需要为关联添加一些条件:

    has_many :messages, -> { select('messages.*, message_tags.status as read')) }
    

    然后是这样的:

    Conversation.joins(:phones)
      .where('phones.id' => 2)
      .order('last_message_at DESC')
      .includes(:messages => :message_tags)
      .where(:message_tags => { :user_id => current_user.id })
    

    【讨论】:

    • 肯定越来越近了;我没想过改变 has_many 声明。范围之类的东西对此有用吗?
    • 你只能加入/包含关联,所以我看不出范围特别有用。有什么突出的问题?
    • 问题是我还在学习Rails。一条消息有很多标签,但用户应该只能看到他们的标签。我想将他们的标签作为一列包含在消息中,使用他们的 user_id 从标签连接表中获取它。
    • User has_many :message_tags, through: :messages User.includes(:message_tags),瞧。
    猜你喜欢
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    • 2022-01-09
    • 2021-10-08
    • 2017-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多