Rails 4 批量更新模型数组
Rails 4 bulk updating array of models
我有一组 ActiveRecord 模型,我想重新编号一列并批量更新它们。
代码如下所示:
rules = subject.email_rules.order(:number)
rules.each_with_index do |rule, index|
rule.number = index + 1
end
EmailRule.update(rules.map(&:id), rules.map { |r| { number: r.number } })
但这会创建 N SQL 个语句,我想要 1 个,有没有办法做到这一点?
您的一个替代方案是将所有交互放在一个事务中,它至少会在最后进行一次提交,从而使其速度更快。
ActiveRecord::Base.transaction do
...
end
假设您使用的是 postgres,您可以使用 row_number
和看起来有些奇怪的 UPDATE/FROM 结构。这是基本版本:
UPDATE email_rules target
SET number = src.idx
FROM (
SELECT
email_rules.id,
row_number() OVER () as idx
FROM email_rules
) src
WHERE src.id = target.id
您可能需要将其限定在 subject
上,当然还包括按数字排序,如下所示:
UPDATE email_rules target
SET number = src.idx
FROM (
SELECT
email_rules.id,
row_number() OVER (partition by subject_id) as idx
FROM email_rules
ORDER BY number ASC
) src
WHERE src.id = target.id
(假设subject_id
是关联subjects/email_rules的外键)
我有一组 ActiveRecord 模型,我想重新编号一列并批量更新它们。 代码如下所示:
rules = subject.email_rules.order(:number)
rules.each_with_index do |rule, index|
rule.number = index + 1
end
EmailRule.update(rules.map(&:id), rules.map { |r| { number: r.number } })
但这会创建 N SQL 个语句,我想要 1 个,有没有办法做到这一点?
您的一个替代方案是将所有交互放在一个事务中,它至少会在最后进行一次提交,从而使其速度更快。
ActiveRecord::Base.transaction do
...
end
假设您使用的是 postgres,您可以使用 row_number
和看起来有些奇怪的 UPDATE/FROM 结构。这是基本版本:
UPDATE email_rules target
SET number = src.idx
FROM (
SELECT
email_rules.id,
row_number() OVER () as idx
FROM email_rules
) src
WHERE src.id = target.id
您可能需要将其限定在 subject
上,当然还包括按数字排序,如下所示:
UPDATE email_rules target
SET number = src.idx
FROM (
SELECT
email_rules.id,
row_number() OVER (partition by subject_id) as idx
FROM email_rules
ORDER BY number ASC
) src
WHERE src.id = target.id
(假设subject_id
是关联subjects/email_rules的外键)