json
列に格納されている配列内の要素を検索するにはどうすればよいですか? (更新:jsonb
列の9.4更新された回答も参照してください。)
このようなJSONドキュメントがある場合、json
という名前のblob
列に格納されます。
{"name": "Wolf",
"ids": [185603363281305602,185603363289694211]}
私ができることは次のようなものです:
SELECT * from "mytable" WHERE 185603363289694211 = ANY("blob"->'ids');
一致するすべての行を取り出します。ただし、"blob"->'ids'
はPostgres配列ではなくJSON値を返すため、これは機能しません。
可能であれば、個々のIDにインデックスを作成することもできます。
以下の元の回答はPostgres 9.3にのみ適用されます。 Postgres 9.4の回答については、以下の更新を参照してください。
これは Erwinの参照された回答 に基づいて構築されていますが、この質問にはもう少し明確です。
この場合のIDはbigint
sなので、JSON配列をPostgres bigint
配列に変換するヘルパー関数を作成します。
CREATE OR REPLACE FUNCTION json_array_bigint(_j json)
RETURNS bigint[] AS
$$
SELECT array_agg(elem::text::bigint)
FROM json_array_elements(_j) AS elem
$$
LANGUAGE sql IMMUTABLE;
代わりに、ここでtext
配列を簡単に(そしておそらく再利用可能に)返すことができます。 bigint
でのインデックス作成はtext
よりもはるかに高速だと思いますが、それを裏付ける証拠をオンラインで見つけるのは困難です。
インデックスを作成する場合:
CREATE INDEX "myindex" ON "mytable"
USING GIN (json_array_bigint("blob"->'ids'));
クエリの場合、これは機能し、インデックスを使用します。
SELECT * FROM "mytable"
WHERE '{185603363289694211}' <@ json_array_bigint("blob"->'ids');
これを行うとクエリにも機能しますが、インデックスは使用しません。
SELECT * FROM "mytable"
WHERE 185603363289694211 = ANY(json_array_bigint("blob"->'ids'));
9.4のアップデート
Postgres 9.4はjsonb
タイプを導入しました。 これは良いSO jsonb
についての回答であり、json
を超えて使用する必要がある場合 。要するに、 JSONをクエリする場合は、jsonb
を使用する必要があります。
列をjsonb
として構築する場合は、次のクエリを使用できます。
SELECT * FROM "mytable"
WHERE blob @> '{"ids": [185603363289694211]}';
@>
はPostgresの包含演算子です jsonb
についてはここに記載 。 Alain's answer に感謝します。
最初に、->>
ではなく演算子 ->
を試して、配列値からJSONレイヤーを削除します。
次に、queryは次のように機能します。
新しいPostgreSQL JSONデータ型内のフィールドを使用してクエリするにはどうすればよいですか?
また、indexingは次のように機能します。
JSON配列で要素を見つけるためのインデックス
久しぶりだね...
Postgresql-9.5では、簡単にクエリを実行できるようになりました。
select '{"name": "Wolf",
"ids": [185603363281305602,185603363289694211]}'::jsonb
@> '{"ids":[185603363281305602]}'
代わりにjsonb
フィールドを使用する必要があり、後でインデックス化できます。
CREATE INDEX idx_gin_ids ON mytable USING gin ((blob -> 'ids'));