Zoeken…


Invoering

JSON - Java Script Object Notation, Postgresql ondersteunt JSON Gegevenstype sinds versie 9.2. Er zijn een aantal vooraf gedefinieerde functies en operators voor toegang tot de JSON-gegevens. De operator -> retourneert de sleutel van de JSON-kolom. De operator ->> retourneert de waarde van JSON-kolom.

Een pure JSON-tabel maken

Om een pure JSON-tabel te maken, moet u een enkel veld met het type JSONB :

CREATE TABLE mytable (data JSONB NOT NULL);

U moet ook een basisindex maken:

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

Op dit punt kunt u gegevens in de tabel invoegen en deze efficiënt opvragen.

Complexe JSON-documenten opvragen

Een complex JSON-document in een tabel opnemen:

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"
        }
    }
}
$$);

Zoekopdracht voor een element op het hoogste niveau:

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

Zoekopdracht voor een eenvoudig item in een array:

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

Zoekopdracht voor een object in een array:

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

Zoekopdracht voor een genest object:

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

Prestaties van @> vergeleken met -> en ->>

Het is belangrijk om het prestatieverschil te begrijpen tussen het gebruik van @> , -> en ->> in het WHERE gedeelte van de query. Hoewel deze twee vragen in grote lijnen equivalent zijn:

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

de eerste instructie gebruikt de hierboven gemaakte index, terwijl de laatste twee dat niet zullen doen, wat een volledige tabelscan vereist.

Het is nog steeds toegestaan om de -> operator te gebruiken bij het verkrijgen van resulterende gegevens, dus de volgende vragen zullen ook de index gebruiken:

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

JSONb-operatoren gebruiken

Een DB en een tabel maken

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
);

De DB vullen

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" } }'
);

Laten we alles in de tafelboeken bekijken:

SELECT * FROM books;

Output:

-> operator retourneert waarden uit JSON-kolommen

1 kolom selecteren:

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

Output:

voer hier de afbeeldingsbeschrijving in

2 kolommen selecteren:

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

Output:

voer hier de afbeeldingsbeschrijving in

-> vs ->>

De operator -> retourneert het oorspronkelijke JSON-type (dit kan een object zijn), terwijl ->> tekst retourneert.

Retourneer NESTED-objecten

U kunt de -> om een genest object terug te geven en zo de operatoren te ketenen:

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

Output:

voer hier de afbeeldingsbeschrijving in

filtering

Selecteer rijen op basis van een waarde in uw JSON:

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

Let op WHERE gebruikt -> dus we moeten vergelijken met JSON '"Dharma Bums"'

Of we kunnen ->> en vergelijken met 'Dharma Bums'

Output:

voer hier de afbeeldingsbeschrijving in

Geneste filtering

Zoek rijen op basis van de waarde van een genest JSON-object:

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

Output:

voer hier de afbeeldingsbeschrijving in

Een echt voorbeeld

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

We gaan evenementen in deze tabel opslaan, zoals paginaweergaven. Elke gebeurtenis heeft eigenschappen, die van alles kunnen zijn (bijv. Huidige pagina) en verzendt ook informatie over de browser (zoals besturingssysteem, schermresolutie, enz.). Beide zijn volledig gratis van vorm en kunnen in de loop van de tijd veranderen (omdat we denken aan extra dingen om bij te houden).

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 } }'
);

Laten we nu alles selecteren:

SELECT * FROM events;

Output:

voer hier de afbeeldingsbeschrijving in

JSON-operators + PostgreSQL-aggregatiefuncties

Met behulp van de JSON-operators, gecombineerd met traditionele PostgreSQL-aggregatiefuncties, kunnen we eruit halen wat we willen. U hebt de volledige macht van een RDBMS tot uw beschikking.

  • Laten we het gebruik van de browser bekijken:

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

Output:

voer hier de afbeeldingsbeschrijving in

  • Totale omzet per bezoeker:

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

Output:

voer hier de afbeeldingsbeschrijving in

  • Gemiddelde schermresolutie

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

Output:

voer hier de afbeeldingsbeschrijving in

Meer voorbeelden en documentatie hier en hier .



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow