Jak przesyłać zapytania przy użyciu pól w nowym typie danych JSON PostgreSQL?

216

Szukam niektórych dokumentów i / lub przykładów nowych funkcji JSON w PostgreSQL 9.2.

W szczególności biorąc pod uwagę serię rekordów JSON:

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

Jak napisać SQL, aby znaleźć rekord według nazwy?

W waniliowym SQL:

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

Oficjalna instrukcja dla programistów jest dość rzadka:

Aktualizacja I

Mam ułożyła sens szczegółowo, co jest obecnie możliwe z PostgreSQL 9.2 . Korzystając z niektórych niestandardowych funkcji, można wykonywać następujące czynności:

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

Aktualizacja II

Teraz przeniosłem moje funkcje JSON do ich własnego projektu:

PostSQL - zestaw funkcji do przekształcania PostgreSQL i PL / v8 w całkowicie niesamowity magazyn dokumentów JSON

Toby Hede
źródło
3
Niedawno znalazłem ten post na blogu autorstwa Matta Schinckela, który szczegółowo wyjaśnia zapytania JSON w PostgreSQL schinckel.net/2014/05/25/querying-json-in-postgres
knowbody
1
@knowbody Ten post dotyczy zapytań o JSONB, co różni się od JSON. Moje zło za to, że nie wyjaśniłem tego w poście.
Matthew Schinckel,

Odpowiedzi:

177

Postgres 9.2

Cytuję Andrew Dunstana na liście hakerów pgsql :

Na pewnym etapie prawdopodobnie będą pewne funkcje przetwarzania jsonów (w przeciwieństwie do produkcji jsonów), ale nie w wersji 9.2.

Nie przeszkadza mu to w dostarczeniu przykładowej implementacji w PLV8 która powinna rozwiązać Twój problem.

Postgres 9.3

Oferuje arsenał nowych funkcji i operatorów, aby dodać „przetwarzanie json”.

Odpowiedź na pierwotne pytanie w Postgres 9.3:

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

Zaawansowany przykład:

W przypadku większych tabel możesz dodać indeks wyrażeń w celu zwiększenia wydajności:

Postgres 9.4

Dodaje jsonb(b dla „binarnego”, wartości są przechowywane jako rodzime typy Postgres) i jeszcze więcej funkcjonalności dla obu typów. Oprócz wspomnianych wyżej indeksów ekspresji jsonbobsługuje także indeksy GIN, btree i hash , przy czym GIN jest najsilniejszy z nich.

Podręcznik sięga tak daleko, jak sugeruje:

Ogólnie rzecz biorąc, większość aplikacji powinna preferować przechowywanie danych JSON jako jsonb , chyba że istnieją dość wyspecjalizowane potrzeby, takie jak wcześniejsze założenia dotyczące porządkowania kluczy obiektowych.

Odważny nacisk moje.

Wydajność korzysta z ogólnych ulepszeń indeksów GIN.

Postgres 9.5

Kompletne jsonbfunkcje i operatory. Dodaj więcej funkcji do manipulowania jsonbw miejscu i do wyświetlania.

Erwin Brandstetter
źródło
1
Dzięki, bardzo szybko napotkałem problemy z typem przy użyciu podejścia PLV8. Wygląda obiecująco, ale w tej chwili nie nadaje się do użytku.
Toby Hede
@TobyHede: Chyba będziemy musieli poczekać na 9.3.
Erwin Brandstetter
1
@JoeShaw: Dzięki, odpowiednio zaktualizowałem i dodałem link do Wiki Postgres.
Erwin Brandstetter,
@ErwinBrandstetter, jeśli szukam GDZIE elem - >> 'correct' = 'TRUE'; a JSON wygląda następująco: „poprawny”: „PRAWDA”, jaki jest właściwy sposób zapytania warunków logicznych?
Shiraj
@Shiraj: Zadaj nowe pytania jako pytanie . Komentarze nie są tym miejscem.
Erwin Brandstetter,
87

W Postgres 9.3+ wystarczy użyć ->operatora. Na przykład,

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

zobacz http://clarkdave.net/2013/06/what-can-you-do-with-postgresql-and-json/, aby uzyskać kilka dobrych przykładów i samouczek.

Meekohi
źródło
2
W powyższym przykładzie należy mieć pole o nazwie dataz dokumentem JSON: {images:{thumbnail:{url:'thumbnail.jpg'}}}. Daj nam znać, jak wyglądają Twoje dane i jakie zapytanie nie działa.
Meekohi
6
Jak zapytać, czy istnieje tablica? Widzę operatora # >>, ale nie mam pojęcia, jak go używać!
Mohamed El Mahallawy
Czy w tym zapytaniu wybierz mogę użyć symboli wieloznacznych? To znaczySELECT data->'%'->'thumbnail'->'url' AS thumb FROM instagram;
Bharat,
@ Odpowiedź Meekohi działa dobrze: konkretnie nie potrzebowałem, ::jsonjak opisano w innych postach. Pamiętaj również, że ->operator zgłasza błąd, jeśli spróbujesz uzyskać dostęp do właściwości, która nie istnieje (tj. Jeśli rozłożyłeś JSON):ERROR: column "jsonPropertyYouWant" does not exist
Red Pea
19

Z postgres 9.3 użyj -> do dostępu do obiektu. 4 przykład

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

szyny c

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

zwroty

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

Możesz kontynuować zagnieżdżanie

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

powrót

 data
------
 1
(1 row)
joseAndresGomezTovar
źródło