Comment interroger à l'aide de champs à l'intérieur du nouveau type de données JSON PostgreSQL?

216

Je recherche des documents et / ou des exemples pour les nouvelles fonctions JSON dans PostgreSQL 9.2.

Plus précisément, compte tenu d'une série d'enregistrements JSON:

[
  {name: "Toby", occupation: "Software Engineer"},
  {name: "Zaphod", occupation: "Galactic President"}
]

Comment pourrais-je écrire le SQL pour trouver un enregistrement par son nom?

Dans vanilla SQL:

SELECT * from json_data WHERE "name" = "Toby"

Le manuel de développement officiel est assez rare:

Mettre à jour I

J'ai rassemblé un résumé détaillant ce qui est actuellement possible avec PostgreSQL 9.2 . En utilisant certaines fonctions personnalisées, il est possible de faire des choses comme:

SELECT id, json_string(data,'name') FROM things
WHERE json_string(data,'name') LIKE 'G%';

Mise à jour II

J'ai maintenant déplacé mes fonctions JSON dans leur propre projet:

PostSQL - un ensemble de fonctions pour transformer PostgreSQL et PL / v8 en un magasin de documents JSON totalement génial

Toby Hede
la source
3
Tout récemment, j'ai trouvé ce billet de blog de Matt Schinckel, qui explique en détail la requête JSON dans PostgreSQL schinckel.net/2014/05/25/querying-json-in-postgres
knowbody
1
@knowbody Ce message concerne en fait l'interrogation de JSONB, qui est assez distincte de JSON. C'est dommage de ne pas avoir clarifié cela dans le post.
Matthew Schinckel

Réponses:

177

Postgres 9.2

Je cite Andrew Dunstan sur la liste pgsql-hackers :

À un certain stade, il y aura peut-être des fonctions de traitement json (par opposition à la production json), mais pas en 9.2.

Cela ne l'empêche pas de fournir un exemple d'implémentation en PLV8 qui devrait résoudre votre problème.

Postgres 9.3

Offre un arsenal de nouvelles fonctions et opérateurs pour ajouter "json-processing".

La réponse à la question d'origine dans Postgres 9.3:

SELECT *
FROM   json_array_elements(
  '[{"name": "Toby", "occupation": "Software Engineer"},
    {"name": "Zaphod", "occupation": "Galactic President"} ]'
  ) AS elem
WHERE elem->>'name' = 'Toby';

Exemple avancé:

Pour les tables plus grandes, vous souhaiterez peut-être ajouter un index d'expression pour augmenter les performances:

Postgres 9.4

Ajouts jsonb(b pour "binaire", les valeurs sont stockées en tant que types Postgres natifs) et encore plus de fonctionnalités pour les deux types. En plus des index d'expression mentionnés ci-dessus, jsonbprend également en charge les index GIN, btree et hash , le GIN étant le plus puissant d'entre eux.

Le manuel va jusqu'à suggérer:

En général, la plupart des applications devraient préférer stocker les données JSON sous la forme jsonb , sauf s'il existe des besoins assez spécialisés, tels que des hypothèses héritées sur l'ordre des clés d'objet.

Accentuation mienne.

Les performances bénéficient d'améliorations générales des index GIN.

Postgres 9.5

jsonbFonctions et opérateurs complets . Ajoutez plus de fonctions à manipuler jsonbsur place et à afficher.

Erwin Brandstetter
la source
1
Merci, j'ai rencontré des problèmes de type très rapidement en utilisant l'approche PLV8. Semble prometteur, mais pas vraiment utilisable pour le moment.
Toby Hede
@TobyHede: Je suppose que nous devrons attendre 9.3 alors.
Erwin Brandstetter
1
@JoeShaw: Merci, j'ai mis à jour en conséquence et ajouté un lien vers le wiki Postgres.
Erwin Brandstetter
@ErwinBrandstetter si je cherche OERE elem - >> 'correct' = 'TRUE'; et le JSON ressemble à ceci: "correct": "TRUE", quelle est la bonne façon d'interroger les termes logiques?
Shiraj
@Shiraj: Veuillez poser les nouvelles questions comme question . Les commentaires ne sont pas le lieu.
Erwin Brandstetter
87

Avec Postgres 9.3+, utilisez simplement l' ->opérateur. Par exemple,

SELECT data->'images'->'thumbnail'->'url' AS thumb FROM instagram;

voir http://clarkdave.net/2013/06/what-can-you-do-with-postgresql-and-json/ pour de beaux exemples et un tutoriel.

Meekohi
la source
2
Dans l'exemple ci - dessus , vous devriez avoir un champ nommé dataun document JSON: {images:{thumbnail:{url:'thumbnail.jpg'}}}. Faites-nous savoir à quoi ressemblent vos données et quelle requête échoue.
Meekohi
6
Comment pouvez-vous demander s'il existe un tableau? Je vois l'opérateur # >> mais je ne sais pas comment l'utiliser!
Mohamed El Mahallawy
Dans cette requête de sélection, puis-je utiliser un caractère générique? C'est à direSELECT data->'%'->'thumbnail'->'url' AS thumb FROM instagram;
Bharat
@ La réponse de Meekohi fonctionne bien: en particulier, je n'avais pas besoin ::jsoncomme décrit dans d'autres articles. Notez également que l' ->opérateur lèvera une erreur si vous essayez d'accéder à une propriété qui n'existe pas (c'est-à-dire si vous avez échelonné JSON):ERROR: column "jsonPropertyYouWant" does not exist
The Red Pea
19

Avec postgres 9.3, utilisez -> pour l'accès aux objets. 4 exemple

seed.rb

se = SmartElement.new
se.data = 
{
    params:
    [
        {
            type: 1,
            code: 1,
            value: 2012,
            description: 'year of producction'
        },
        {
            type: 1,
            code: 2,
            value: 30,
            description: 'length'
        }
    ]
}

se.save

rails c

SELECT data->'params'->0 as data FROM smart_elements;

Retour

                                 data
----------------------------------------------------------------------
 {"type":1,"code":1,"value":2012,"description":"year of producction"}
(1 row)

Vous pouvez continuer l'imbrication

SELECT data->'params'->0->'type' as data FROM smart_elements;

revenir

 data
------
 1
(1 row)
joseAndresGomezTovar
la source