Come eseguire una query utilizzando i campi all'interno del nuovo tipo di dati JSON PostgreSQL?


216

Sto cercando alcuni documenti e / o esempi per le nuove funzioni JSON in PostgreSQL 9.2.

In particolare, data una serie di record JSON:

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

Come scriverei l'SQL per trovare un record per nome?

In SQL vaniglia:

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

Il manuale ufficiale degli sviluppatori è abbastanza scarso:

Aggiornamento I.

Ho messo insieme un riassunto di ciò che è attualmente possibile con PostgreSQL 9.2 . Utilizzando alcune funzioni personalizzate, è possibile fare cose come:

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

Aggiornamento II

Ora ho spostato le mie funzioni JSON nel loro progetto:

PostSQL : un insieme di funzioni per trasformare PostgreSQL e PL / v8 in un fantastico archivio di documenti JSON


3
Di recente ho trovato questo post sul blog di Matt Schinckel, che spiega in dettaglio l'interrogazione di JSON in PostgreSQL schinckel.net/2014/05/25/querying-json-in-postgres
knowbody

1
@knowbody Questo post riguarda in realtà la query su JSONB, che è abbastanza distinto da JSON. Il mio male per non averlo reso più chiaro nel post.
Matthew Schinckel,

Risposte:


177

Postgres 9.2

Cito Andrew Dunstan nella lista degli hacker di pgsql :

Ad un certo punto ci saranno probabilmente alcune funzioni di elaborazione json (anziché di produzione json), ma non in 9.2.

Non gli impedisce di fornire un'implementazione di esempio in PLV8 che dovrebbe risolvere il tuo problema.

Postgres 9.3

Offre un arsenale di nuove funzioni e operatori per aggiungere "json-processing".

La risposta alla domanda originale in Postgres 9.3:

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

Esempio avanzato:

Per le tabelle più grandi potresti voler aggiungere un indice di espressione per aumentare le prestazioni:

Postgres 9.4

Aggiunge jsonb(b per "binario", i valori sono memorizzati come tipi Postgres nativi) e ancora più funzionalità per entrambi i tipi. Oltre agli indici di espressione sopra menzionati, jsonbsupporta anche gli indici GIN, btree e hash , il GIN è il più potente di questi.

Il manuale arriva fino a suggerire:

In generale, la maggior parte delle applicazioni dovrebbe preferire archiviare i dati JSON come jsonb , a meno che non ci siano esigenze abbastanza specializzate, come ipotesi legacy sull'ordinamento di chiavi oggetto.

Enorme enfasi sulla mia.

Le prestazioni traggono vantaggio da miglioramenti generali degli indici GIN.

Postgres 9.5

jsonbFunzioni e operatori completi . Aggiungi più funzioni da manipolare jsonbsul posto e per la visualizzazione.


1
Grazie, ho riscontrato problemi di tipo molto velocemente usando l'approccio PLV8. Sembra promettente, ma non utilizzabile al momento.
Toby Hede,

@TobyHede: Suppongo che dovremo aspettare 9.3.
Erwin Brandstetter,

1
@JoeShaw: Grazie, ho aggiornato di conseguenza e ho aggiunto un link al Wiki di Postgres.
Erwin Brandstetter,

@ErwinBrandstetter se sto cercando WHERE elem - >> 'correct' = 'VERO'; e JSON si presenta così: "corretto": "VERO", qual è il modo giusto di interrogare i termini logici?
Shiraj,

@Shiraj: si prega di porre le nuove domande come domanda . I commenti non sono il posto giusto.
Erwin Brandstetter,

87

Con Postgres 9.3+, basta usare l' ->operatore. Per esempio,

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

vedi http://clarkdave.net/2013/06/what-can-you-do-with-postgresql-and-json/ per alcuni begli esempi e un tutorial.


2
Nell'esempio di cui sopra si dovrebbe avere un campo denominato datacon un documento JSON: {images:{thumbnail:{url:'thumbnail.jpg'}}}. Facci sapere come sono i tuoi dati e quale query non riesce.
Meekohi,


6
Come si può fare una query se esiste un array? Vedo l'operatore # >> ma non ho idea di come usarlo!
Mohamed El Mahallawy,

In questa query di selezione è possibile utilizzare il carattere jolly? Vale a direSELECT data->'%'->'thumbnail'->'url' AS thumb FROM instagram;
Bharat,

La risposta di @ Meekohi funziona bene: in particolare non avevo bisogno ::jsoncome descritto in altri post. Si noti inoltre che l' ->operatore genererà un errore se si tenta di accedere a una proprietà che non esiste (ovvero se si è scaglionato JSON):ERROR: column "jsonPropertyYouWant" does not exist
The Red Pea,

19

Con Postgres 9.3 usa -> per l'accesso agli oggetti. 4 esempio

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

rotaie c

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

ritorna

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

Puoi continuare a nidificare

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

ritorno

 data
------
 1
(1 row)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.