任意のデータを挿入する必要があるperson
テーブルがあります。私はPostgres 9.4を使用しているので、jsonb
が正しい選択のようです。
データの例:
id: 1, name: "Joe Doe", preferences: { color: "red" , toy: "car"}
id: 2, name: "Jane Doe", preferences: { color: "blue", food: "hamburguer" }
問題は、変数値でクエリする必要があることです。例:
好みに「ハンバーガー」を持っているすべての人、および部分的なクエリも可能でなければならないので、「バーグ」を検索すると、レコード2が表示されます。
Json関数を使用して、キーを知っている限り、値を検索できますよね?または、値をすばやく検索する方法はありますか?
私がやろうとしていることは、tsvector列を作成し、jsonをダンプして全文検索を使用して部分クエリを実行することです。
私は _MATERIALIZED VIEW
_ をネストされていない値と検索ツールとしてのトライグラムインデックスとともに使用することをお勧めします。
hstore
ネストされた値が必要ない場合は、hstore
の方が適している場合があります。関数 svals(hstore)
を使用して、hstore
値のネストを解除します。
追加モジュールhstore
をデータベースごとに1回インストールする必要があります。
_CREATE EXTENSION hstore;
_
_CREATE TABLE person AS
SELECT * FROM (
VALUES
(1, 'Joe Doe', hstore 'toy=>car, color=>red')
, (2, 'Jane Doe', 'food=>hamburguer, color=>blue')
) t(person_id, name, preferences);
_
_CREATE MATERIALIZED VIEW person_pref AS
SELECT p.person_id, j.preference -- just pref
FROM person p, svals(p.preferences) j(preference);
_
これは、セットを返す関数svals()
に対する暗黙的な_CROSS JOIN LATERAL
_です。
追加モジュール_pg_trgm
_をデータベースごとに1回インストールする必要があります。
_CREATE EXTENSION pg_trgm;
_
次に:
_CREATE INDEX person_pref_j_trgm_idx ON person_pref_j
USING gin (preference gin_trgm_ops);
_
詳細:
_SELECT *
FROM person p
WHERE EXISTS (
SELECT 1
FROM person_pref pp
WHERE pp.person_id = p.person_id
AND pp.preference ILIKE '%burg%'
);
_
これはかなり速いことに注意してください。
jsonb
ネストされた値または numeric
またはboolean
values がある場合、jsonb
の方が効率的です。上記と同じことを jsonb_each_text(jsonb)
で実行できます。
_CREATE TABLE person AS
SELECT * FROM (
VALUES
(1, 'Joe Doe', jsonb '{"toy": "car", "color": "red"}')
, (2, 'Jane Doe', '{"food": "hamburguer", "color": "blue"}')
) t(person_id, name, preferences);
CREATE MATERIALIZED VIEW person_pref AS
SELECT p.person_id, j.key, j.preference -- incl. key or just pref?
FROM person_j p, jsonb_each_text(p.preferences) j(key, preference);
_
同じインデックス、同じクエリ。あなたmightがMVにキーを追加し、それも検索したい場合:
_CREATE INDEX person_pref_trgm_idx ON person_pref_j
USING GIN (key gin_trgm_ops, preference gin_trgm_ops);
_