如何将数据从关联表的列迁移到hstore列?

时间:2014-11-10 23:25:09

标签: ruby-on-rails postgresql hstore

我正在通过创建带有*_localeslocale字段的关联name表来完成本地化的项目。我正在将其迁移到使用hstore列(使用Postgres),但我没有正确的语法。

结构现在就像这样

table: thingy_locales
  locale :string
  name   :string
  thingy_id : integer


table: thingies
  name_translations :hstore

在迁移中,我希望将thingy_locales表中的所有数据移至name_translations字段,密钥为'en'(因为目前只有' en&#39 ; thingy_locales表中的区域设置。)

所以我试过这个

execute "UPDATE thingies t SET name_translations=(select (\"'en'\" => \"'|name|'\")::hstore from thingy_locales where thingy_id = t.id);"

但是这给了我

PG::UndefinedColumn: ERROR:  column "'en'" does not exist
LINE 1: ...ort_categories loc SET name_translations=(select ("'en'" => ...
                                                             ^

我做错了什么?

4 个答案:

答案 0 :(得分:1)

我不知道自动执行SQL命令,但您可能希望进行多次迁移:

  • 将hstore列添加到thingies
  • 迭代所有thingy_locales,将它们读入散列/哈希值。然后做Thingy.create!(name_translations: {'en' => hash})
  • 删除thingy_locales

Rails中的迁移可以包含任意代码。由于这是一个转换数据的实例,因此在Ruby中执行它可能是最安全的选择。

如果速度是一个问题,那么你可能需要寻求优化的SQL查询,但坦率地说,如果你不担心速度,不要为自己造成麻烦。

答案 1 :(得分:1)

实际上,只要再看一下你的代码,假设你有这种关联:

class Thingy
  has_many :thingy_locales
end

class ThingyLocale
  belongs_to :thingy
end

看起来你想做的事情就像这样:

Thingy.all.each do |thingy|
  name = thingy.thingy_locales.where(locale: 'en').first.select(:name)
  thingy.name_translations = {'en' => name}
  thingy.save!
end

答案 2 :(得分:1)

好的,我让它上班了。

execute "UPDATE thingies t SET name_translations=hstore('en', (select name from thingy_locales where thingy_id = t.id));"

完美地完成工作

答案 3 :(得分:1)

不要试图通过Ruby研磨大量数据,在数据库中进行。立即想到两种方法:

  1. 在UPDATE中使用相关子查询:

    connection.execute(%q{
      update thingies
      set name_translations = (
        select hstore(array_agg(locale), array_agg(name))
        from thingy_locales
        where thingy_id = thingies.id
      )
    })
    
  2. 加入UPDATE中的派生表:

    connection.execute(%q{
      update thingies
      set name_translations = dt.h
      from (
        select hstore(array_agg(locale), array_agg(name)) as h, thingy_id
        from thingy_locales
        group by thingy_id
      ) as dt
      where id = dt.thingy_id
    })
    
  3. 两者的核心是使用hstore(text[], text[]) function构建hstorearray_agg function来构建hstore(text[], text[])想要的键和值数组。

    不要害怕在迁移中将SQL引入connection.execute次调用。假装你的数据库太愚蠢而无法做任何有趣的事情在Rails应用程序中可能是纯粹的意识形态,但它是一种非生产性和不专业的态度。从长远来看,通过学习SQL以及数据库的工作方式,您将获得更好的服务。

相关问题