J'ai un champ appelé "utilisateur" qui contient un tableau json qui ressemble à peu près à ceci:
"user"
:
[{ "_id" : "1", "count" : "4" }, { "_id" : "3", "count": "4"}]
Maintenant, je veux une requête comme:
select count from tablename where id = "1"
Je ne parviens pas à obtenir le champ particulier count
à partir d'un tableau d'objets json dans PostgreSQL 9.4.
Il serait beaucoup plus efficace de stocker vos valeurs dans un schéma normalisé. Cela dit, vous pouvez également le faire fonctionner avec votre configuration actuelle.
En supposant cette définition de table:
CREATE TABLE tbl (tbl_id int, usr jsonb);
"utilisateur" est un mot réservé et nécessiterait des guillemets doubles pour être utilisé comme nom de colonne. Ne fais pas ça. J'utilise à la place usr
.
La requête n'est pas aussi triviale que les commentaires (maintenant supprimés) semblaient:
SELECT t.tbl_id, obj.val->>'count' AS count
FROM tbl t
JOIN LATERAL jsonb_array_elements(t.usr) obj(val) ON obj.val->>'_id' = '1'
WHERE t.usr @> '[{"_id":"1"}]';
Il y a 3 étapes de base:
WHERE t.usr @> '[{"_id":"1"}]'
Identifie les lignes avec l'objet correspondant dans le tableau JSON. L'expression peut utiliser un index GIN générique sur la colonne jsonb
, ou un avec la classe d'opérateur plus spécialisée jsonb_path_ops
:
CREATE INDEX tbl_usr_gin_idx ON tbl USING gin (usr jsonb_path_ops);
La clause WHERE
ajoutée est logiquement redondante , mais elle est requise pour utiliser l'index. L'expression dans la clause join applique la même condition mais seulement après unnesting du tableau dans chaque ligne qualifiée jusqu'à présent. Avec la prise en charge des index, Postgres ne traite que les lignes contenant un objet éligible pour commencer. Peu importe avec les petites tables, fait une différence énorme avec les grandes tables et seulement quelques lignes qualificatives.
En relation:
Unnest avec jsonb_array_elements()
. ( unnest()
n'est valable que pour les types de tableaux Postgres.) Comme nous ne sommes intéressés que par la mise en correspondance d'objets, filtrez immédiatement la condition de jointure.
En relation:
'count'
Une fois les objets éligibles extraits, simplement: obj.val->>'count'
.