受信者と呼ばれるjsonbフィールドを持つpostgresql 9.4データベースにテーブルがあります。いくつかの例の行:
[{"id": "145119603", "name": "145119603", "type": 2}]
[{"id": "1884595530", "name": "1884595530", "type": 1}]
[{"id": "363058213", "name": "363058213", "type": 1}]
[{"id": "1427965764", "name": "1427965764", "type": 1}]
[{"id": "193623800", "name": "193623800", "type": 0}, {"id": "419955814", "name": "419955814", "type": 0}]
[{"id": "624635532", "name": "624635532", "type": 0}, {"id": "1884595530", "name": "1884595530", "type": 1}]
[{"id": "791712670", "name": "791712670", "type": 0}]
[{"id": "895207852", "name": "895207852", "type": 0}]
[{"id": "144695994", "name": "144695994", "type": 0}, {"id": "384217055", "name": "384217055", "type": 0}]
[{"id": "1079725696", "name": "1079725696", "type": 0}]
Idの値のリストがあり、jsonbフィールドの配列内で、そのリストのいずれかの値を持つオブジェクトを含む行を選択したい。
それは可能ですか?これを高速化するGINインデックスはありますか?
役立つ単一の操作はありませんが、いくつかのオプションがあります。
1。照会するIDの数が少ない(かつ固定されている)場合、複数の包含演算子_@>
_をor
と組み合わせて使用できます。 f.ex .:
_where data @> '[{"id": "1884595530"}]' or data @> '[{"id": "791712670"}]'
_
単純なgin
インデックスは、ここのデータ列で役立ちます。
2。可変数のIDを持っている場合(またはそれらがたくさんある場合)、json[b]_array_elements()
を使用してそれぞれを抽出できます配列の要素、IDリストを作成してから、任意の包含演算子_?|
_でクエリします:
_select *
from jsonbtest
where to_json(array(select jsonb_array_elements(data) ->> 'id'))::jsonb ?|
array['1884595530', '791712670'];
_
残念ながら、サブクエリを含む式にインデックスを付けることはできません。インデックスを作成する場合は、そのための関数を作成する必要があります。
_create function idlist_jsonb(jsonbtest)
returns jsonb
language sql
strict
immutable
as $func$
select to_json(array(select jsonb_array_elements($1.data) ->> 'id'))::jsonb
$func$;
create index on jsonbtest using gin (idlist_jsonb(jsonbtest));
_
この後、次のようなIDを照会できます。
_select *, jsonbtest.idlist_jsonb
from jsonbtest
where jsonbtest.idlist_jsonb ?| array['193623800', '895207852'];
_
注:ここでは ドット表記/計算フィールド を使用しましたが、その必要はありません。
3。しかし、この時点では、json [b]に固執する必要はありません:PostgreSQLでサポートされている単純なテキスト配列がありますも。
_create function idlist_array(jsonbtest)
returns text[]
language sql
strict
immutable
as $func$
select array(select jsonb_array_elements($1.data) ->> 'id')
$func$;
create index on jsonbtest using gin (idlist_array(jsonbtest));
_
そして、オーバーラップ配列演算子_&&
_でこの計算フィールドをクエリします。
_select *, jsonbtest.idlist_array
from jsonbtest
where jsonbtest.idlist_array && array['193623800', '895207852'];
_
注:私の内部テストから、この後者のソリューションはjsonbバリアントよりも高いコストで計算されますが、実際にはそれより少し高速です。パフォーマンスが本当に重要な場合は、両方をテストする必要があります。
私は回避策を見つけます:where data::text similar to '%("id": "145119603"|"id": "1884595530")%'