3

usersというjsonbフィールドを持つテーブルがありますdata。特定の文字列に一致する列のを持つすべてのユーザーを取得する必要があります。data例えば:

user1 = data: {"property_a": "a1", "property_b": "b1"}
user2 = data: {"property_a": "a2", "property_b": "b2"}

dataに一致する値を持つユーザーを取得したいのですが'b2'、この場合は になります'user2'

これをエレガントな方法で行う方法はありますか?すべてのユーザーからすべてのキーを取得しdata、手動でクエリを作成できますが、高速でもエレガントでもありません。

さらに、一致したキーと値を取得する必要がありますが、まず最初に。

4

2 に答える 2

7

簡単な方法はありません。ドキュメントごと:

GIN インデックスを使用して、多数の jsonb ドキュメント (データム) 内で発生するキーまたはキーと値のペアを効率的に検索できます。

大胆強調鉱山。すべての値に対するインデックスはありません。(互換性のないデータ型を持つことができます!) すべてのキーの名前がわからない場合は、すべての行のすべての JSON 値を検査する必要があります。

あなたが示すようなキーが2つしかない場合(またはよく知られているキーがいくつかある場合)、それでも十分に簡単です:

SELECT *
FROM   users
WHERE  data->>'property_a' = 'b2' OR
       data->>'property_b' = 'b2';

単純な式 indexでサポートできます:

CREATE INDEX foo_idx ON users ((data->>'property_a'), (data->>'property_b'))

またはGIN インデックスを使用する場合:

SELECT *
FROM   users
WHERE  data @> '{"property_a": "b2"}' OR
       data @> '{"property_b": "b2"}'

CREATE INDEX bar_idx ON users USING gin (data jsonb_path_ops);

すべてのキー名を知っているわけではない場合、事態はさらに複雑になります...

jsonb_each()またはjsonb_each_text()を使用して、すべての値をセットにネスト解除し、ANY構成でチェックできます。

SELECT *
FROM   users
WHERE  jsonb '"b2"' = ANY (SELECT (jsonb_each(data)).value);

または

...
WHERE  'b2' = ANY (SELECT (jsonb_each_text(data)).value);

デシベル<>ここでフィドル

ただし、最後のインデックスはサポートされていません。代わりに、すべての値を配列に抽出し、その上に式インデックスを作成し、配列演算子を使用してクエリでその式を一致させることができます...

関連している:

于 2015-04-13T17:36:19.170 に答える
5

このクエリを試してください。

SELECT * FROM users
WHERE data::text LIKE '%b2%'

もちろん、キーにそのような文字列も含まれている場合は機能しません。

于 2015-12-28T06:43:16.513 に答える