CodeGym /Kursy /SQL SELF /Łączenie i modyfikacja obiektów JSON z operatorem || i fu...

Łączenie i modyfikacja obiektów JSON z operatorem || i funkcją jsonb_concat()

SQL SELF
Poziom 34 , Lekcja 0
Dostępny

Jeśli JSONB to magiczna skrzynia, do której wrzucamy dane, to || i jsonb_concat() to narzędzia, które pozwalają te skrzynie łączyć albo zmieniać ich zawartość. W realu możesz potrzebować połączyć kilka obiektów JSON, dodać dane z jednego do drugiego albo połączyć tablice w jedną listę.

Na przykład, wyobraź sobie, że masz dwa obiekty JSONB:

{"name": "Alice", "age": 25}

i

{"city": "Wonderland", "hobbies": ["czytanie", "szachy"]}

Chcesz dostać:

{"name": "Alice", "age": 25, "city": "Wonderland", "hobbies": ["czytanie", "szachy"]}

Albo połączyć dwie tablice JSONB:

[1, 2, 3]

i

[4, 5, 6]

żeby wynik wyglądał tak:

[1, 2, 3, 4, 5, 6]

To wszystko ogarniesz przez || albo jsonb_concat(). Zobaczmy jak to działa.

Operator || do łączenia JSONB

Operator || pozwala łączyć dwa obiekty lub tablice JSONB w PostgreSQL. Jest prosty, szybki i łatwy w użyciu. Oto główne zasady działania:

  • Jeśli łączysz dwa obiekty JSONB, wynikowy obiekt będzie miał klucze i wartości z obu obiektów.
  • Jeśli klucze się powtarzają, wartość z prawego operanda nadpisuje wartość z lewego.
  • Jeśli łączysz tablice JSONB, elementy lewej i prawej tablicy są łączone w jedną tablicę.

Przykład 1: Łączenie dwóch obiektów JSONB

SELECT '{"name": "Alice", "age": 25}'::jsonb || '{"city": "Wonderland", "hobbies": ["czytanie", "szachy"]}'::jsonb AS merged_object;

Wynik:

{"name": "Alice", "age": 25, "city": "Wonderland", "hobbies": ["czytanie", "szachy"]}

Przykład 2: Aktualizacja wartości przy powtarzających się kluczach

SELECT '{"name": "Alice", "age": 25}'::jsonb || '{"age": 30, "city": "Wonderland"}'::jsonb AS updated_object;

Wynik:

{"name": "Alice", "age": 30, "city": "Wonderland"}

Zwróć uwagę, że wartość klucza "age" z prawego obiektu nadpisała wartość z lewego.

Przykład 3: Łączenie tablic

SELECT '[1, 2, 3]'::jsonb || '[4, 5, 6]'::jsonb AS merged_array;

Wynik:

[1, 2, 3, 4, 5, 6]

Funkcja jsonb_concat() do łączenia JSONB

Funkcja jsonb_concat() działa podobnie jak operator ||, ale daje więcej elastyczności, jeśli chcesz jej użyć w funkcjach, triggerach albo dynamicznych zapytaniach. Przyjmuje dwa argumenty typu JSONB i zwraca połączony wynik.

Przykład: użycie jsonb_concat()

SELECT jsonb_concat('{"a": 1, "b": 2}'::jsonb, '{"b": 3, "c": 4}'::jsonb) AS combined;

Wynik:

{"a": 1, "b": 3, "c": 4}

Łączenie obiektów i tablic: szczegóły i niuanse

Łącząc obiekty z powtarzającymi się kluczami, pamiętaj, że wartości z prawego obiektu mają priorytet.

Na przykład:

SELECT '{"key1": "wartosc1"}'::jsonb || '{"key1": "wartosc2"}'::jsonb AS result;

Wynik:

{"key1": "wartosc2"}

Jeśli nie chcesz nadpisywać wartości, trzymaj takie dane pod osobnymi kluczami albo użyj innego podejścia (np. tablicy).

A tablice zawsze są łączone przez dodanie elementów z prawej tablicy do lewej. Na przykład:

SELECT '["a", "b"]'::jsonb || '["c", "d"]'::jsonb AS result;

Wynik:

["a", "b", "c", "d"]

Jeśli w tablicy są obiekty, kolejność obiektów zostaje zachowana:

SELECT '[{"id": 1}, {"id": 2}]'::jsonb || '[{"id": 3}]'::jsonb AS result;

Wynik:

[{"id": 1}, {"id": 2}, {"id": 3}]

Praktyczne przykłady

Aktualizacja profilu użytkownika. Załóżmy, że mamy tabelę users, gdzie profile są trzymane w formacie JSONB:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    profile JSONB
);

INSERT INTO users (profile) VALUES ('{"name": "Alice", "age": 25}');

Teraz chcemy dodać miasto zamieszkania:

UPDATE users 
SET profile = profile || '{"city": "Wonderland"}'
WHERE id = 1;

Wynik zapytania:

{"name": "Alice", "age": 25, "city": "Wonderland"}

Łączenie danych o zamówieniach. Załóżmy, że mamy tabelę orders:

CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    details JSONB
);

INSERT INTO orders (details) VALUES ('{"items": [{"product": "laptop", "quantity": 1}]}');

Teraz dodajemy kolejny produkt do zamówienia:

UPDATE orders
SET details = jsonb_set(
    details,
    '{items}',
    details->'items' || '[{"product": "mysz", "quantity": 2}]'::jsonb
)
WHERE id = 1;

Wynik zapytania:

{"items": [{"product": "laptop", "quantity": 1}, {"product": "mysz", "quantity": 2}]}

Różnice między || a jsonb_concat()

Funkcjonalnie operator || i funkcja jsonb_concat() są identyczne. Używaj ||, jeśli piszesz proste zapytania, bo zapis jest krótszy. Funkcja jsonb_concat() jest wygodna, gdy musisz jawnie wywołać ją w programie albo triggerze.

Typowe błędy i jak ich unikać

Błąd: próba połączenia niekompatybilnych typów.

SELECT '{"key": "wartosc"}'::jsonb || '["wartosc"]'::jsonb;

Wynik:

ERROR:  cannot concatenate jsonb objects and arrays

Tu po lewej masz obiekt, a po prawej tablicę — PostgreSQL nie ogarnia takiego połączenia. Żeby operacja się udała, oba operandy muszą być tego samego typu: albo dwa obiekty, albo dwie tablice.

Przeoczenie: brak indeksów przy pracy z JSONB

Jeśli często filtrujesz dane po wartościach w polach JSONB, a nie masz indeksów — zapytania mogą mocno zamulać. To nie jest błąd w klasycznym sensie, ale skutki dla wydajności są bardzo odczuwalne. Nie zapomnij o GIN-indeksach:

CREATE INDEX idx_profile_data ON employees USING gin(profile);
2
Zadanie
SQL SELF, poziom 34, lekcja 0
Niedostępne
Aktualizacja obiektu JSONB z uwzględnieniem zamiany kluczy
Aktualizacja obiektu JSONB z uwzględnieniem zamiany kluczy
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION