【问题标题】:Load only part of associated object仅加载关联对象的一部分
【发布时间】:2018-04-06 07:10:50
【问题描述】:

我的RequestAttachment 有一个课程ProjectRequestsArchive

class ProjectRequestsArchive < ApplicationRecord
  has_one :request_attachment, 
           foreign_key: "request_id", 
           primary_key: "request_id", 
           required: true
end


class RequestAttachment < ApplicationRecord
    belongs_to :project_requests_archive,
               foreign_key: :request_id,
               primary_key: :request_id
end

RequestAttachment 类包含 BLOB 属性。

所以当我调用ProjectRequestsArchive.find(1054).request_attachment 时,它生成的 SQL 看起来像

 RequestAttachment Load (24.7ms)  SELECT  `request_attachments`.* 
                                  FROM `request_attachments` 
                                  WHERE  `request_id` = 634 LIMIT 1

注意:这个操作花了大约 10 秒,但我在 request_id 上设置了索引,所以现在它需要 1 秒,这也太可怕了。

问题:

我的问题是,我可以只加载请求的ID,而不加载整个 BLOB 吗?我不需要将它加载到内存中,我只想加载ID

我可以看到上面的 SQL 输出,有select request_attachments.*

当我使用 ProjectRequestsArchive.find(1054).request_attachment.id 时,它还会创建 SQL:select *

我想获取 SQL 查询,它只选择 ID:SELECT id from request_attachmens。有什么办法吗?我无法通过某种延迟加载或类似的方式来解决它。

编辑:

我忘了提,ProjectRequestArchive.request_id 映射到 RequestAttachmet.request_id

RequestAttachment.idRequestAttachment.request_id 不同。 我需要提取ID

【问题讨论】:

  • 嗯。请更正键名;现在他们都有相同的名字。此外,加载 RequestAttachment.where(...).pluck(id) 可以解决您的问题。
  • 很遗憾,由于给定的架构,键名无法更改。'这个解决方案看起来不错,但我需要从 ProjectRequestsArchive 类中获取它。
  • 我根本不关注它。如果所有键都是request_id,要获得request_id,您可能只需使用request_id,在您的示例中为634
  • 在最简单的形式中,我只需要使用关联对象提取request_id,如ProjectRequestsArchive.find(1054).request_attachment.id 所示,但不加载整个对象,而只加载ID。当然还有另一种解决方案,但我很好奇是否有办法这样做。
  • 哦,对不起,我忘了提一件事。请查看已编辑的问题。

标签: ruby-on-rails ruby orm associations


【解决方案1】:

如果您希望 sql 选择数据库上的特定列,可以使用select(*fields)

像这样使用它:

Model.select("id, col1, col2").find() // and so on

现在查询日志应该是这样的:

SELECT id, col1, col2 FROM "models" ...

希望这会有所帮助!

【讨论】:

  • 有一个问题,ProjectRequestsArchive.find(1054).request_attachment.select(:id) 不起作用。 Select 不能用于关联对象。如何获得ID 有很多选择,但我想通过上面的示例了解是否有办法做到这一点。
  • .select('associated_table.column')
【解决方案2】:

它应该是开箱即用的延迟加载。如果您只想要 ID,请检查 ProjectRequestsArchive.first.request_id 并且应该在第一次触摸后加载 ProjectRequestsArchive.first.request_attachment

【讨论】:

  • 哦,对不起,我忘了提一些事情。请查看已编辑的问题。
【解决方案3】:

试试这个查询:

RequestAttachmet.joins(:project_requests_archive).where(
  project_requests_archives: { id: 1054 }
).pluck(:id)

【讨论】:

  • 是的,这个解决方案有效,但这不是我想要的。我想找到一个使用关联对象的解决方案。所以我想使用的解决方案应该看起来像这样ProjectRequestsArchive.find(1054).request_attachment.id
  • 好的,你能解释一下什么有效,什么无效?以便更清楚实际需求并更新答案。
  • 这个解决方案也使用关联对象引用,我没有让你明白这一点。只是语法偏好吗?
  • ProjectRequestsArchive 具有关联模型 RequestAttachment。所以如果我想加载一个相关的对象,我会使用ProjectRequestsArchive.first.request_attachment。由此,我只想选择关联对象的id,而不是所有属性。
  • 如果是这样,它将触发您在帖子中提到的数据库查询。祝你好运
猜你喜欢
  • 2013-05-11
  • 2020-10-26
  • 1970-01-01
  • 1970-01-01
  • 2019-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多