首页 > 解决方案 > 将mysql查询转换为rails查询

问题描述

大家好我在将mysql查询转换为rails查询时遇到问题。我有这些模型-

class User < ApplicationRecord
   has_many :comments, foreign_key: "commenter_id"
end

class Comment < ApplicationRecord
  belongs_to :commenter, class_name: "User"
end

谁能帮我将以下查询转换为rails查询-

UPDATE comments 
INNER JOIN users on comments.commenter_id = users.id 
SET comments.deleted_at = users.deleted_at 
WHERE users.deleted_at IS NOT NULL

我正在尝试对其评论者被软删除的软删除评论。

更新1:到目前为止,我可以通过使用这个来做到这一点-

User.only_deleted.includes(:comments).find_each do |u|
  u.comments.update_all(deleted_at: u.deleted_at)
end

但我想在单个查询上执行此操作,而不必遍历结果。

更新2:我正在使用acts_as_paranoid gem,因此需要取消范围的用户,我的最终查询变为:

User.unscoped{Comment.joins(:commenter).where.not(users: {deleted_at: nil}).update_all("comments.deleted_at = users.deleted_at") 

标签: mysqlruby-on-rails

解决方案


这应该适用于 MySQL:

Comment
    .joins(:user)
    .where.not(users: { deleted_at: nil })
    .update_all("comments.deleted_at = users.deleted_at")

这在 Postgres 上不起作用,因为它缺少用户的 FROM 子句。

一个性能较差但多语言的选项是:

Comment
  .joins(:user)
  .where.not(users: { deleted_at: nil })
  .update_all("deleted_at = ( SELECT users.deleted_at FROM users WHERE comments.id = users.id )")

这仍然可能比遍历 Ruby 中的记录好一个数量级,因为您消除了应用服务器和数据库之间的流量延迟。


推荐阅读