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?JOIN LATERAL jsonb_array_elements(t.usr) obj(value) is short for JOIN LATERAL jsonb_array_elements(t.usr) AS obj(value)
et quiobj(value)
est un alias de table et de colonne? Dans cet exemple, s'ilobj
s'agit d'un alias de table, à quoi sert-il un alias? L'ensemble est revenu dejsonb_array_elements
?JOIN LATERAL jsonb_array_elements(t.usr) obj ON obj->>'_id' = '1'
eu le même effet (une fois que vous avez mis à jour l'instruction select à utiliser à lavalue
place deval
). Il semble quejsonb_array_elements(t.usr)
renvoie un tableau avec une seule colonne. Les postgres sont-ils intelligents et réalisent-ilsobj ->>
la même chose queobj.val ->>
?