Sök…


Introduktion

JSON - Java Script Object Notation, Postgresql stöder JSON Datatyp sedan 9.2 version. Det finns vissa fördefinierade funktioner och operatörer för att få åtkomst till JSON-data. Operatören -> returnerar nyckeln till JSON-kolumnen. Operatören ->> returnerar värdet på JSON Column.

Skapa ett rent JSON-bord

För att skapa en ren JSON-tabell måste du ange ett enda fält med typen JSONB :

CREATE TABLE mytable (data JSONB NOT NULL);

Du bör också skapa ett grundläggande index:

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

Vid denna punkt kan du infoga data i tabellen och fråga dem effektivt.

Fråga efter komplexa JSON-dokument

Ta ett komplext JSON-dokument i en tabell:

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

Fråga för ett toppnivåelement:

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

Fråga efter ett enkelt objekt i en matris:

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

Fråga efter ett objekt i en matris:

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

Fråga för ett kapselt objekt:

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

Prestanda för @> jämfört med -> och ->>

Det är viktigt att förstå resultatskillnaden mellan att använda @> , -> och ->> i WHERE delen av frågan. Även om dessa två frågor verkar vara i stort sett likvärdiga:

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

det första uttalandet kommer att använda indexet som skapats ovan medan de två senare inte kommer att kräva en fullständig tabellscanning.

Det är fortfarande tillåtet att använda operatören -> när man skaffar resulterande data, så följande frågor kommer också att använda indexet:

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

Använda JSONb-operatörer

Skapa en DB och en tabell

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

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

Låter se allt inne i bordsböckerna:

SELECT * FROM books;

Produktion:

-> operatören returnerar värden från JSON-kolumnerna

Att välja 1 kolumn:

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

Produktion:

ange bildbeskrivning här

Att välja två kolumner:

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

Produktion:

ange bildbeskrivning här

-> vs ->>

Operatören -> returnerar den ursprungliga JSON-typen (som kan vara ett objekt), medan ->> returnerar text.

Returnera NESTED-objekt

Du kan använda -> att returnera ett kapselt objekt och därmed kedja operatörerna:

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

Produktion:

ange bildbeskrivning här

Filtrering

Välj rader baserat på ett värde i din JSON:

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

Lägg märke till VAR använder -> så vi måste jämföra med JSON '"Dharma Bums"'

Eller så kan vi använda ->> och jämföra med 'Dharma Bums'

Produktion:

ange bildbeskrivning här

Kapslad filtrering

Hitta rader baserade på värdet på ett kapslat JSON-objekt:

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

Produktion:

ange bildbeskrivning här

Ett verkligt exempel

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

Vi kommer att lagra händelser i den här tabellen, som sidvisningar. Varje evenemang har egenskaper som kan vara vad som helst (t.ex. aktuell sida) och skickar också information om webbläsaren (som OS, skärmupplösning osv.). Båda dessa är helt fria och kan förändras över tid (eftersom vi tänker på extra saker att spåra).

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

Nu kan vi välja allt:

SELECT * FROM events;

Produktion:

ange bildbeskrivning här

JSON-operatörer + PostgreSQL aggregerade funktioner

Med hjälp av JSON-operatörerna, i kombination med traditionella PostgreSQL-aggregeringsfunktioner, kan vi dra ut vad vi vill. Du har en fullständig styrka av ett RDBMS till ditt förfogande.

  • Låter se webbläsaranvändning:

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

Produktion:

ange bildbeskrivning här

  • Total intäkt per besökare:

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

Produktion:

ange bildbeskrivning här

  • Genomsnittlig skärmupplösning

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

Produktion:

ange bildbeskrivning här

Fler exempel och dokumentation här och här .



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow