2014-06-17 26 views
4

目前,我有以下DB模式:遷移JSON列類型HSTORE列類型

create_table :user_actions do |t| 
    t.integer :emitter_id 
    t.string :emitter_type 
    t.integer :target_id 
    t.string :target_type 
    t.json  :payload 
    t.timestamps 
end 

而且我想給​​場遷移從jsonhstore

執行以下操作:

以下錯誤消息
change_column :user_actions, :payload, :hstore 

結果:

PG::DatatypeMismatch: ERROR: column "payload" cannot be cast automatically to type hstore 
HINT: Specify a USING expression to perform the conversion. 

不知道如何使用USING提示,什麼是應該做這種遷移不會丟失任何的最佳方式數據?

+0

確實[這個例子](http://www.postgresql.org/docs /9.3/static/hstore.html#AEN149208)有幫助嗎? (F.16.6。兼容性) – DrColossos

+0

這可能是可行的@DrColossos示例顯示了postgres using子句。我不太瞭解ruby/activerecord,我確實發現了這個線程:https://github.com/rails/rails/issues/11062它表明1)你不能通過activerecord和2獲得使用條款)解決方法是直接到SQL。 – Greg

+0

Thx,實際上去了一個簡單的解決方案,重命名列並做一個簡單的遷移'o.new_field = o.payload'其中'new_field'是一個'hstore' –

回答

11

提示:指定使用表達式來執行轉換

其實格式爲:

change_column :user_actions, :payload, '[type_to_which_you_want_to_change] USING CAST(data AS [type_to_which_you_want_to_change])' 

所以在你的情況下:

change_column :user_actions, :payload, 'hstore USING CAST(payload AS hstore)' 

參考:

https://stackoverflow.com/a/25032193/1222852

+1

這是行不通的。 Postgres無法使用自定義函數將JSON轉換爲HSTORE。看到我的答案確實奏效。 – l85m

+0

解決了我正面臨的問題。 –

1

找到一個簡單但工作的解決方案。創建一個名爲parameters新列,並做了簡單的遷移腳本:

def up 
    add_column :user_actions, :parameters, :hstore 

    UserAction.find_each do |o| 
    o.parameters = o.payload 
    o.save! 
    end 

    remove_column :user_actions, :payload 
end 

def down 
    add_column :user_actions, :payload, :json 

    UserAction.find_each do |o| 
    o.payload = o.parameters 
    o.save! 
    end 

    remove_column :user_actions, :parameters 
end 
1

Taimoor Changaiz的答案是部分不正確因爲PostgreSQL不能施放JSON無需使用自定義功能HSTORE。假設你的JSON不是嵌套的,這裏是將工作:

def self.up 
    execute <<-SQL 
     CREATE OR REPLACE FUNCTION my_json_to_hstore(json) 
       RETURNS hstore 
       IMMUTABLE 
       STRICT 
       LANGUAGE sql 
      AS $func$ 
       SELECT hstore(array_agg(key), array_agg(value)) 
       FROM json_each_text($1) 
      $func$; 
     SQL 
    change_column :user_actions, :payload, 'hstore USING my_json_to_hstore(payload)' 
    end 

    def self.down 
    change_column :user_actions, :payload, 'json USING CAST(payload AS json)' 
    execute "DROP FUNCTION my_json_to_hstore(json)" 
    end 

感謝pozs爲他定製的PostgreSQL的功能在這裏:Casting JSON to HSTORE in Postgres 9.3+?