La réponse originale suivante s'applique uniquement à Postgres 9.3. Pour une réponse Postgres 9.4, voir la mise à jour ci-dessous.
Cela s'appuie sur les réponses référencées d'Erwin , mais est un peu plus explicite à cette question.
Les identifiants dans ce cas sont bigint
s, créez donc une fonction d'assistance pour convertir un tableau JSON en un Postgres bigint
tableau :
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;
Nous aurions pu facilement (et peut-être de manière plus réutilisable) renvoyer un text
tableau ici à la place. Je soupçonne l'indexation sur bigint
est beaucoup plus rapide que text
mais j'ai du mal à trouver des preuves en ligne pour étayer cela.
Pour construire l'index :
CREATE INDEX "myindex" ON "mytable"
USING GIN (json_array_bigint("blob"->'ids'));
Pour l'interrogation, cela fonctionne et utilise l'index :
SELECT * FROM "mytable"
WHERE '{185603363289694211}' <@ json_array_bigint("blob"->'ids');
Cela fonctionnera également pour les requêtes, mais cela n'utilisera pas l'index :
SELECT * FROM "mytable"
WHERE 185603363289694211 = ANY(json_array_bigint("blob"->'ids'));
Mise à jour pour 9.4
Postgres 9.4 a introduit le jsonb
taper. C'est une bonne réponse SO à propos de jsonb
et quand l'utiliser sur json
. En bref, si jamais vous interrogez le JSON, vous devez utiliser jsonb
.
Si vous créez votre colonne en tant que jsonb
, vous pouvez utiliser cette requête :
SELECT * FROM "mytable"
WHERE blob @> '{"ids": [185603363289694211]}';
Le @>
est l'opérateur contient de Postgres, documenté pour jsonb
ici
.Merci à la réponse d'Alain
d'avoir porté cela à mon attention.