[go: up one dir, main page]
More Web Proxy on the site http://driver.im/

日々雑記

旅行の事ばっかり。神社成分多め。
Recent Tweets@

メモ。 調べた時のバージョンは、PostgreSQLは9.4.0で、Railsは4.2.0。

JSONBデータ型とは

バイナリ型JSONの事。JSONBの"B"はバイナリ(binary)のB。

元々PostgreSQLでは9.2からJSON型に対応しており、9.4からJSONを独自バイナリ形式で格納するJSONB型が追加された。

JSONBの特徴をざっと書くと以下のような感じ

  • データの正規化が行われ、入力結果が完全に保持されないケースがある(不要な要素の間の空白文字の削除、重複したキーがあった場合に後述したもののみ有効となる等)
  • 格納容量が大きくなる傾向にある。また、正規化が行われる為、格納処理は普通のJSON型の比べて遅い。
  • 検索がJSONと比べて格段に早い

基本的に、検索に特化している感じらしい。 JSONBについての詳細は、@nuko_yokohamaさんのJSONBデータ型を使ってみようが大変詳しいのでおすすめです。

Railsから使う

マイグレーションファイル

4.2からRails本体でJSONBに対応しているので、特にgem等は必要無し。型にjsonbを指定してあげればOK。

bin/rails generate model event payload:jsonb
  def change
    create_table :events do |t|
      t.jsonb :payload

      t.timestamps null: false
    end
    add_index(:events, :payload, using: 'gin')
  end

こんな感じで。インデックスはGINインデックスで。 GINインデックスについては前書いたので割愛。

データの作成

Hashにしてから入れるのも、JSON形式のStringそのまま入れるのも、どっちも大丈夫そう。

Event.create(payload: { kind: "user_renamed", change: ["jack", "john"]})
Event.first.payload  # => {"kind"=>"user_renamed", "change"=>["jack", "john"]}

Event.create(payload: '{"title": "Example Schema", "type": "object", "properties": { "firstName": { "type": "string"}, "lastName": { "type": "string" } } }')
Event.last.payload
# => {"type"=>"object", "title"=>"Example Schema", "properties"=>{"lastName"=>{"type"=>"string"}, "firstName"=>{"type"=>"string"}}}

先に書いた通り、重複したキーは削除される。

Event.create(payload: '{"user_name": "test1", "user_name": "test2"}')
Event.last.payload  # => {"user_name"=>"test2"}

上記の場合、user_nameキーが重複しているので、最初に定義したtest1の値が破棄される。

検索

PostgreSQLではJSON用の演算子や関数が幾つか定義されているのですが、Rails本体では特にラッパーとかは提供されてないので、それらの演算子を使いたい場合は、普通にwhereメソッドで指定してあげればOK。

Event.where("payload->>'name' = ?", "test1")
# => #<:relation id: payload:>"test1"}, created_at: "2015-02-11 01:09:40", updated_at: "2015-02-11 01:09:40">]>
</:relation>

演算子・関数の詳細はこちらを参照。

で、一個問題があって、JSONB用の一部の演算子に"?“ が使われていて、これがActiveRecordのプレースホルダ用の演算子(”?“)とバッティングしています。

なので、今はプレースホルダとJSONBの一部演算子を一緒にwhereを使う事が出来ない。 使えないのはこの辺り。key/element内に指定して値がいるかどうかの存在チェック用演算子。 ActiveRecordのプレースホルダに”?“以外の記号を使えるようにするPRが見た覚えがあるので、いずれ改善されるかも。

まとめ

ちょっと癖と一部演算子の問題があるものの、頻繁に検索するデータであれば、JSONB使うのが良さそうかなと。

 Text
  1. act2012bl reblogged this from y-yagi
  2. atm09td reblogged this from y-yagi
  3. y-yagi posted this