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.
Hypothèses
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 usr
place.
Requete
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 :
1. Identifiez les lignes éligibles à moindre coût
WHERE t.usr @> '[{"_id":"1"}]'
identifie les lignes avec un objet correspondant dans le tableau JSON. L'expression peut utiliser un index GIN générique sur la jsonb
colonne, 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 WHERE
clause ajoutée est logiquement redondante , mais elle est requise pour utiliser l'index. L'expression de la clause join applique la même condition, mais uniquement après avoir supprimé le 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 de petites tables, fait une énorme différence avec de grandes tables et seulement quelques lignes qualificatives.
En relation:
2. Identifiez les objets correspondants dans le tableau
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:
3. Extraire la valeur de la clé imbriquée 'count'
Après des objets qualifiés ont été extraites, tout simplement: obj.val->>'count'
.
obj(value)
vient-il? Est-ce sur leLATERAL JOIN
, lejsonb_array_elements
ou ailleurs?