web-dev-qa-db-fra.com

Comment obtenir un objet particulier du tableau jsonb dans PostgreSQL?

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.

15
Rabi C Shah

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 place usr.

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 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:

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'

Une fois les objets éligibles extraits, simplement: obj.val->>'count'.

17
Erwin Brandstetter