4

使用 activerecord 使用 hstore 列更新多条记录的好方法是什么?现在我正在循环,更新和保存这样的:

time = Time.now.to_s
scoped_tasks.each do |task|
  task.data[:last_checked] = time
  task.save!
end

有没有办法通过update_all查询来做到这一点?我见过的一种解决方案如下所示:

MyModel.update_all(:properties => ActiveRecord::Coders::Hstore.dump({'a' => 1}))

但问题在于它会覆盖整个列,因此其他值会丢失。我也看过这个:

MyModel.update_all("data = data || hstore('a', 'blah')")

但出于某种原因,我会收回0价值。它看起来也只有在 hstore 为空时才有效。

4

2 回答 2

6

我自己也遇到了同样的问题,这是我能够解决的方法:

MyModel.update_all([%(data = data || hstore(?,?)), 'a', 'new_value']))

对此的核心修复是将 update_all 操作包装在 [] 和 %() 中。我仍在努力弄清楚 %() 如何在 Postgre SQL 中定义 SET,所以如果有人有一个非常有用的解释。

在我的情况下,我实际上也删除了一个键(真的我想更新键名但保留值)。因此,如果有人遇到这个问题,代码如下所示:

MyModel.update_all([%(data = delete("data",?)), 'a'])

我希望在同一个调用中执行这两个操作,但这会在 SQL 中创建一个非常奇怪的命令,其中第二个操作是作为 WHERE 子句的一部分而不是 SET 添加的。对我来说仍然有点黑魔法,但希望这会有所帮助......

于 2014-04-25T19:06:07.983 回答
0

如果你使用

MyModel.update_all(:properties => ActiveRecord::Coders::Hstore.dump({'a' => 1}))

那么它将清除其他值,如果您尝试使用

MyModel.update_all("data = data || hstore('a', 'blah')")它仅在 hstore 列中有任何值时才有效,因此请尝试将两者结合使用

if (hstore_column_name).present? MyModel.update_all("data = data || hstore('a', 'blah')") else MyModel.update_all(:properties => ActiveRecord::Coders::Hstore.dump({'a' => 1}))

于 2017-05-20T08:18:19.573 回答