【问题标题】:Update all with a join of child attributes使用子属性的连接更新所有
【发布时间】:2021-06-28 10:00:25
【问题描述】:

如何对存储在我的帖子中的 cache_attribute :cached_comment_infos 执行批量更新

应该是这样的:

Post.joins(:comments).where(id: post_ids).update_all(
  cached_comment_infos: self.comments.pluck(:author_name, :reference).map { |v| v.join("/") }.join(", ")
)

每个帖子的预期输出应该是这样的:"John Doe/3242, Tom Jed/6264"

【问题讨论】:

    标签: mysql ruby-on-rails ruby


    【解决方案1】:

    我不认为你想要update_all。 update_all 会将所有记录更新为一个值。

    https://apidock.com/rails/v4.0.2/ActiveRecord/Relation/update_all

    文档中给出的示例是将所有Customerwants_email 设置为true

      Customer.update_all wants_email: true
    

    您可以遍历帖子并在唯一的 sql 语句中更新每个帖子

      Post.joins(:comments).where(id: post_ids).each do |post|
        post.cached_comment_infos = post.comments.pluck(:author_name, :reference).map { |v| v.join("/") }.join(", ")
        post.save
      end
    

    如果您真的希望它发生在一个 SQL 语句中,您可以查看 gem activerecord-import。您需要使用他们的“重复密钥更新”功能:https://github.com/zdennis/activerecord-import#duplicate-key-update

    【讨论】:

    • 我们可以使用Post.joins(:comments).eager_load(:comments).each {|post| post.update(:cached_comment_infos, post.comments.map {|c| "#{c.author_name}/#{c.reference}"}.join(', ') } 使其性能更高一些,它至少会节省 N + 1 用于在循环中加载 cmets(但不是用于 post 对象的 N 更新语句)跨度>
    猜你喜欢
    • 2023-03-10
    • 1970-01-01
    • 2014-01-27
    • 1970-01-01
    • 2016-08-30
    • 1970-01-01
    • 2023-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多