如何在 Rails 中使用带有嵌套数组的 PostgreSQL hstore?

How to use PostreSQL hstore with nested array in Rails?

迁移:

class Preference < ActiveRecord::Migration

  def change
    enable_extension 'hstore'

    create_table :preferences do |t|
      t.hstore :prefs
    end
  end
end

型号:

class Preference < ActiveRecord::Base
  store_accessor :prefs
end

如果 prefs 是诸如 { email:'yes' } 之类的散列,这似乎有效,但不适用于内部包含数组的散列:{ email:[ 'monday', 'tuesday' ]}.

拉hash出来时,数组保存为JSON.

是否有将 hstore 与嵌套哈希和数组一起使用的好方法?

我确实尝试将 array:true 添加到迁移中,但这似乎只允许保存数组而不是散列。

如何使用 Rails 带有嵌套哈希和数组的 PostgreSQL hstore?

Rails 4.2.4,PostgreSQL 9.3.5

您可以简单地在访问时解析 JSON:

class Preference < ActiveRecord::Base
  def prefs
    self[:pref] = json_parse_values self[:pref]
  end

  private
  def json_parse_values(hash)
    hash.map do |key, val|
      begin
        [key, (val.is_a?(String) ? JSON.parse(val) : val)]
      rescue JSON::ParserError => e  
        [key, val]
      end 
    end.to_h
  end
end

解析方法仅在它是字符串时才尝试解析值。如果它引发 ParserError,我们就使用字符串。

PostgreSQL hstore 用于存储文本字符串的键值对。看看hstore docs

我使用 JSON 类型将数组存储为散列中的值。有两种 JSON 数据类型:JSON 和 JSONB。 JSONB 支持索引但速度稍慢,而 JSON 不支持索引但速度更快。您可以在这里阅读它们:JSON Type.

我会做以下事情:

class Preference < ActiveRecord::Migration
  def change
    create_table :preferences do |t|
      t.json :prefs
    end
  end
end

旁注中,hstore 列上的设置 array: true 意味着您要存储一个 hstores 数组。