Ricerca…


introduzione

JSON - Notazione oggetto script Java, Postgresql supporta il tipo di dati JSON dalla versione 9.2. Ci sono alcune funzioni e operatori predefiniti per accedere ai dati JSON. L'operatore -> restituisce la chiave della colonna JSON. L'operatore ->> restituisce il valore della colonna JSON.

Creazione di una tabella JSON pura

Per creare una tabella JSON pura è necessario fornire un campo singolo con il tipo JSONB :

CREATE TABLE mytable (data JSONB NOT NULL);

Dovresti anche creare un indice di base:

CREATE INDEX mytable_idx ON mytable USING gin (data jsonb_path_ops);

A questo punto è possibile inserire i dati nella tabella e interrogarli in modo efficiente.

Interrogazione di documenti JSON complessi

Prendere un documento JSON complesso in una tabella:

CREATE TABLE mytable (data JSONB NOT NULL);
CREATE INDEX mytable_idx ON mytable USING gin (data jsonb_path_ops);
INSERT INTO mytable VALUES($$
{
    "name": "Alice",
    "emails": [
        "[email protected]",
        "[email protected]"
    ],
    "events": [
        {
            "type": "birthday",
            "date": "1970-01-01"
        },
        {
            "type": "anniversary",
            "date": "2001-05-05"
        }
    ],
    "locations": {
        "home": {
            "city": "London",
            "country": "United Kingdom"
        },
        "work": {
            "city": "Edinburgh",
            "country": "United Kingdom"
        }
    }
}
$$);

Query per un elemento di primo livello:

SELECT data->>'name' FROM mytable WHERE data @> '{"name":"Alice"}';

Query per un elemento semplice in un array:

SELECT data->>'name' FROM mytable WHERE data @> '{"emails":["[email protected]"]}';

Query per un oggetto in una matrice:

SELECT data->>'name' FROM mytable WHERE data @> '{"events":[{"type":"anniversary"}]}';

Query per un oggetto nidificato:

SELECT data->>'name' FROM mytable WHERE data @> '{"locations":{"home":{"city":"London"}}}';

Prestazioni di @> rispetto a -> e ->>

È importante capire la differenza di prestazioni tra l'utilizzo di @> , -> e ->> nella parte WHERE della query. Sebbene queste due query sembrino essere sostanzialmente equivalenti:

SELECT data FROM mytable WHERE data @> '{"name":"Alice"}';
SELECT data FROM mytable WHERE data->'name' = '"Alice"';
SELECT data FROM mytable WHERE data->>'name' = 'Alice';

la prima istruzione utilizzerà l'indice creato sopra mentre le ultime due non lo faranno, richiedendo una scansione completa della tabella.

È ancora possibile utilizzare l'operatore -> quando si ottengono i dati risultanti, quindi le seguenti query utilizzeranno anche l'indice:

SELECT data->'locations'->'work' FROM mytable WHERE data @> '{"name":"Alice"}';
SELECT data->'locations'->'work'->>'city' FROM mytable WHERE data @> '{"name":"Alice"}';

Usando gli operatori JSONb

Creazione di un DB e una tabella

DROP DATABASE IF EXISTS books_db;
CREATE DATABASE books_db WITH ENCODING='UTF8' TEMPLATE template0;

DROP TABLE IF EXISTS books;

CREATE TABLE books (
  id SERIAL PRIMARY KEY,
  client TEXT NOT NULL,
  data JSONb NOT NULL
);

Popolazione del DB

INSERT INTO books(client, data) values (
    'Joe', 
    '{ "title": "Siddhartha", "author": { "first_name": "Herman", "last_name": "Hesse" } }'
),(
    'Jenny', 
    '{ "title": "Dharma Bums", "author": { "first_name": "Jack", "last_name": "Kerouac" } }'
),(
    'Jenny', 
    '{ "title": "100 años de soledad", "author": { "first_name": "Gabo", "last_name": "Marquéz" } }'
);

Vediamo tutto all'interno dei libri da tavolo:

SELECT * FROM books;

Produzione:

-> operatore restituisce valori dalle colonne JSON

Selezione di 1 colonna:

SELECT client, 
    data->'title' AS title
    FROM books;

Produzione:

inserisci la descrizione dell'immagine qui

Selezione di 2 colonne:

SELECT client, 
   data->'title' AS title, data->'author' AS author
   FROM books;

Produzione:

inserisci la descrizione dell'immagine qui

-> vs ->>

L'operatore -> restituisce il tipo JSON originale (che potrebbe essere un oggetto), mentre ->> restituisce il testo.

Restituisci oggetti NESTED

Puoi usare -> per restituire un oggetto nidificato e quindi concatenare gli operatori:

SELECT client, 
   data->'author'->'last_name' AS author
   FROM books;

Produzione:

inserisci la descrizione dell'immagine qui

filtraggio

Seleziona le righe in base a un valore all'interno del tuo JSON:

 SELECT 
 client,
 data->'title' AS title
 FROM books
  WHERE data->'title' = '"Dharma Bums"';

Avviso WHERE utilizza -> quindi dobbiamo confrontare con '"Dharma Bums"' di JSON

O potremmo usare ->> e confrontare con 'Dharma Bums'

Produzione:

inserisci la descrizione dell'immagine qui

Filtraggio nidificato

Trova le righe in base al valore di un oggetto JSON nidificato:

SELECT 
 client,
 data->'title' AS title
 FROM books
  WHERE data->'author'->>'last_name' = 'Kerouac';

Produzione:

inserisci la descrizione dell'immagine qui

Un esempio reale

CREATE TABLE events (
  name varchar(200),
  visitor_id varchar(200),
  properties json,
  browser json
);

Stiamo andando a memorizzare eventi in questa tabella, come pagine visualizzate. Ogni evento ha proprietà, che potrebbero essere qualsiasi cosa (ad esempio la pagina corrente) e invia anche informazioni sul browser (come OS, risoluzione dello schermo, ecc.). Entrambi sono completamente gratuiti e potrebbero cambiare nel tempo (poiché pensiamo a cose extra da tenere traccia).

INSERT INTO events (name, visitor_id, properties, browser) VALUES
(
  'pageview', '1',
  '{ "page": "/" }',
  '{ "name": "Chrome", "os": "Mac", "resolution": { "x": 1440, "y": 900 } }'
),(
  'pageview', '2',
  '{ "page": "/" }',
  '{ "name": "Firefox", "os": "Windows", "resolution": { "x": 1920, "y": 1200 } }'
),(
  'pageview', '1',
  '{ "page": "/account" }',
  '{ "name": "Chrome", "os": "Mac", "resolution": { "x": 1440, "y": 900 } }'
),(
  'purchase', '5',
  '{ "amount": 10 }',
  '{ "name": "Firefox", "os": "Windows", "resolution": { "x": 1024, "y": 768 } }'
),(
  'purchase', '15',
  '{ "amount": 200 }',
  '{ "name": "Firefox", "os": "Windows", "resolution": { "x": 1280, "y": 800 } }'
),(
  'purchase', '15',
  '{ "amount": 500 }',
  '{ "name": "Firefox", "os": "Windows", "resolution": { "x": 1280, "y": 800 } }'
);

Ora lascia selezionare tutto:

SELECT * FROM events;

Produzione:

inserisci la descrizione dell'immagine qui

Operatori JSON + funzioni aggregate PostgreSQL

Usando gli operatori JSON, combinati con le tradizionali funzioni di aggregazione di PostgreSQL, possiamo estrarre tutto ciò che vogliamo. Hai tutta la potenza di un RDBMS a tua disposizione.

  • Vediamo l'utilizzo del browser:

      SELECT browser->>'name' AS browser, 
        count(browser)
        FROM events
        GROUP BY browser->>'name';
    

Produzione:

inserisci la descrizione dell'immagine qui

  • Entrate totali per visitatore:

      SELECT visitor_id, SUM(CAST(properties->>'amount' AS integer)) AS total
      FROM events
      WHERE CAST(properties->>'amount' AS integer) > 0
      GROUP BY visitor_id;
    

Produzione:

inserisci la descrizione dell'immagine qui

  • Media risoluzione dello schermo

      SELECT AVG(CAST(browser->'resolution'->>'x' AS integer)) AS width,
        AVG(CAST(browser->'resolution'->>'y' AS integer)) AS height
      FROM events;
    

Produzione:

inserisci la descrizione dell'immagine qui

Altri esempi e documentazione qui e qui .



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow