PostgreSQL menawarkan dukungan yang andal untuk menyimpan dan melakukan query data JSON melalui tipe data json dan jsonb. Tipe jsonb sangat berguna karena menyimpan data dalam format biner, sehingga indexing dan query lebih efisien dibandingkan tipe json yang berbasis teks.
Dalam tutorial ini, kita akan membahas operasi JSON yang paling umum di PostgreSQL dengan contoh praktis yang bisa Anda gunakan di aplikasi Anda.
Sebelum lanjut membaca, saya ingin memperkenalkan database manager PostgreSQL yang modern dan cepat buatan kami, Beekeeper Studio. Editor SQL-nya punya autocomplete saat Anda mengetik, jadi mencoba operator JSON ini jadi cepat, dan gratis digunakan untuk PostgreSQL. Unduh di sini.
Membuat Data JSON
Mari mulai dengan membuat tabel yang memiliki kolom jsonb lalu memasukkan beberapa data contoh:
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
info JSONB
);
-- Insert a customer with basic information
INSERT INTO customers (info) VALUES (
'{"name": "Alice Smith", "email": "alice@example.com", "age": 32, "addresses": [
{"type": "home", "city": "San Francisco", "state": "CA"},
{"type": "work", "city": "Oakland", "state": "CA"}
]}'
);
-- Insert another customer
INSERT INTO customers (info) VALUES (
'{"name": "Bob Johnson", "email": "bob@example.com", "age": 45, "addresses": [
{"type": "home", "city": "Seattle", "state": "WA"}
], "orders": [101, 102, 103]}'
);
Operasi JSON Dasar
Mengambil seluruh dokumen JSON
SELECT info FROM customers WHERE id = 1;
Hasil:
{
"age": 32,
"name": "Alice Smith",
"email": "alice@example.com",
"addresses": [
{"city": "San Francisco", "type": "home", "state": "CA"},
{"city": "Oakland", "type": "work", "state": "CA"}
]
}
Mengekstrak Nilai dari JSON
PostgreSQL menyediakan beberapa operator untuk mengekstrak nilai dari JSON:
Mengekstrak field tertentu dengan operator -> (mengembalikan JSON)
-- Get the name field as JSON
SELECT info -> 'name' FROM customers;
Hasil:
"Alice Smith"
"Bob Johnson"
Mengekstrak field tertentu dengan operator -» (mengembalikan teks)
-- Get the name field as text
SELECT info ->> 'name' AS customer_name FROM customers;
Hasil:
customer_name
----------------
Alice Smith
Bob Johnson
Mengakses objek bersarang
-- Getting the first address (array element 0) city
SELECT info -> 'addresses' -> 0 ->> 'city' AS home_city FROM customers;
Hasil:
home_city
------------
San Francisco
Seattle
Menggunakan operator #> untuk akses path
-- Using the path syntax to get the same value
SELECT info #> '{addresses,0,city}' FROM customers;
Hasil:
"San Francisco"
"Seattle"
Menggunakan operator #» untuk akses path sebagai teks
-- Using the path syntax to get the same value as text
SELECT info #>> '{addresses,0,city}' AS home_city FROM customers;
Hasil:
home_city
------------
San Francisco
Seattle
Memodifikasi Data JSON
PostgreSQL menyediakan beberapa fungsi untuk memodifikasi data JSON:
Menambahkan field dengan jsonb_set
-- Add a new field 'premium_customer' to a customer
UPDATE customers
SET info = jsonb_set(info, '{premium_customer}', 'true')
WHERE id = 1;
Menghapus field dengan operator -
-- Remove the premium_customer field
UPDATE customers
SET info = info - 'premium_customer'
WHERE id = 1;
Menggabungkan objek JSON dengan ||
-- Add multiple fields by merging objects
UPDATE customers
SET info = info || '{"status": "active", "last_login": "2025-03-23"}'::jsonb
WHERE id = 1;
Memperbarui field bersarang
-- Update a nested field (home address state)
UPDATE customers
SET info = jsonb_set(
info,
'{addresses,0,state}',
'"NY"'::jsonb
)
WHERE id = 1;
Query Array JSON
Bekerja dengan array JSON adalah operasi yang umum:
Mendapatkan panjang array
-- Get the number of addresses for each customer
SELECT
info ->> 'name' AS customer_name,
jsonb_array_length(info -> 'addresses') AS address_count
FROM customers;
Hasil:
customer_name | address_count
---------------+--------------
Alice Smith | 2
Bob Johnson | 1
Mengekstrak elemen array tertentu
-- Get the second address (index 1) for Alice
SELECT info -> 'addresses' -> 1 FROM customers WHERE id = 1;
Hasil:
{"city": "Oakland", "type": "work", "state": "CA"}
Unnest array untuk query tiap elemen
-- Unnest the addresses array to query individual addresses
SELECT
c.id,
c.info ->> 'name' AS customer_name,
jsonb_array_elements(c.info -> 'addresses') AS address
FROM customers c;
Hasil:
id | customer_name | address
---+---------------+------------------------------------------------------
1 | Alice Smith | {"city": "San Francisco", "type": "home", "state": "NY"}
1 | Alice Smith | {"city": "Oakland", "type": "work", "state": "CA"}
2 | Bob Johnson | {"city": "Seattle", "type": "home", "state": "WA"}
Memfilter dengan array yang di-unnest
-- Find customers with addresses in CA
SELECT DISTINCT
c.id,
c.info ->> 'name' AS customer_name
FROM customers c,
jsonb_array_elements(c.info -> 'addresses') AS addr
WHERE addr ->> 'state' = 'CA';
Hasil:
id | customer_name
---+--------------
1 | Alice Smith
Memeriksa Key dan Nilai
Memeriksa apakah sebuah key ada
-- Find customers who have the 'orders' key
SELECT id, info ->> 'name' AS customer_name
FROM customers
WHERE info ? 'orders';
Hasil:
id | customer_name
---+--------------
2 | Bob Johnson
Memeriksa nilai di dalam array
-- Find customers with a specific order number
SELECT id, info ->> 'name' AS customer_name
FROM customers
WHERE info -> 'orders' ? '101';
Hasil:
id | customer_name
---+--------------
2 | Bob Johnson
Memeriksa apakah ada elemen array yang cocok
-- Find customers who have an address in Oakland (using path operators)
SELECT id, info ->> 'name' AS customer_name
FROM customers
WHERE info @> '{"addresses": [{"city": "Oakland"}]}';
Hasil:
id | customer_name
---+--------------
1 | Alice Smith
Indexing Data JSON
Untuk database produksi dengan dataset JSON yang besar, indexing yang tepat sangat penting:
Membuat index GIN untuk query containment
-- Create a GIN index for faster containment operations
CREATE INDEX idx_customers_info ON customers USING GIN (info);
Membuat index khusus untuk field JSON
-- Create an index on the 'email' field for fast lookups
CREATE INDEX idx_customers_email ON customers ((info ->> 'email'));
Menggunakan field ber-index dalam query
-- This query can use the index we created above
SELECT id, info ->> 'name' AS customer_name
FROM customers
WHERE info ->> 'email' = 'alice@example.com';
Konversi antara JSON dan Tabel
Mengonversi JSON menjadi baris (jsonb_to_record)
-- Extract JSON fields into a tabular structure
SELECT
id,
rec.name,
rec.email,
rec.age
FROM
customers,
jsonb_to_record(info) AS rec(
name text,
email text,
age int
);
Hasil:
id | name | email | age
---+--------------+-------------------+-----
1 | Alice Smith | alice@example.com | 32
2 | Bob Johnson | bob@example.com | 45
Mengonversi array bersarang menjadi tabel (jsonb_to_recordset)
-- Extract addresses from all customers into a table
SELECT
c.id,
c.info ->> 'name' AS customer_name,
addr.type AS address_type,
addr.city,
addr.state
FROM
customers c,
jsonb_to_recordset(c.info -> 'addresses') AS addr(
type text,
city text,
state text
);
Hasil:
id | customer_name | address_type | city | state
---+---------------+--------------+---------------+------
1 | Alice Smith | home | San Francisco | NY
1 | Alice Smith | work | Oakland | CA
2 | Bob Johnson | home | Seattle | WA
Mengonversi hasil query menjadi JSON
-- Aggregate customer orders into a JSON array
SELECT
c.id,
c.info ->> 'name' AS customer_name,
json_agg(o.order_id) AS orders
FROM
customers c
CROSS JOIN LATERAL (
SELECT jsonb_array_elements_text(c.info -> 'orders') AS order_id
) o
GROUP BY c.id, c.info ->> 'name';
Hasil:
id | customer_name | orders
---+---------------+----------
2 | Bob Johnson | ["101", "102", "103"]
Pertimbangan Performa
Saat bekerja dengan JSON di PostgreSQL, perhatikan pertimbangan performa berikut:
-
Gunakan
jsonb, bukanjson: Tipejsonbmenawarkan performa lebih baik untuk sebagian besar operasi. -
Buat index secara strategis: Gunakan index GIN untuk query containment, tetapi buat index khusus untuk field yang sering di-query.
-
Pertimbangkan denormalisasi dengan hati-hati: Meskipun JSON memungkinkan Anda mendenormalisasi model data, nesting yang berlebihan dapat memengaruhi performa query.
-
Perhatikan pola query: Ekspresi path JSON yang kompleks atau unnest array besar yang sering bisa menjadi operasi yang mahal.
-
Batasi ukuran array: Array JSON yang sangat besar dapat menimbulkan masalah performa saat di-unnest.
-
Pertimbangkan proyeksi: Ekstrak hanya field yang Anda butuhkan daripada mengembalikan seluruh dokumen JSON.
Kesimpulan
Kemampuan JSON di PostgreSQL menjadikannya pilihan tepat untuk aplikasi yang perlu menyimpan dan melakukan query data semi-terstruktur. Dengan operator dan fungsi yang dibahas dalam tutorial ini, Anda dapat bekerja dengan data JSON secara efektif sambil tetap memanfaatkan kekuatan dan keandalan database relasional yang matang.
Untuk model data yang kompleks, pertimbangkan pendekatan hybrid: gunakan tabel terstruktur untuk skema tetap dan data yang sering di-query, serta gunakan JSON untuk data fleksibel tanpa skema atau struktur bersarang yang sulit dimodelkan secara relasional.
Siap mencoba contoh-contoh ini sendiri? Buka Beekeeper Studio dan mulai jelajahi kemampuan JSON PostgreSQL hari ini.
Beekeeper Studio Adalah GUI PostgreSQL Gratis & Open Source
Inilah client PostgreSQL yang selama ini saya cari! UI-nya yang membuatnya beda: bersih, intuitif, dan powerful. Selamat tinggal PGAdmin yang kaku. - David Cyprian
Beekeeper Studio adalah client PostgreSQL yang cepat, intuitif, dan mudah digunakan. Aplikasi ini juga mendukung banyak database lain, dan berjalan mulus di Windows, Mac, dan Linux.
Apa Kata Pengguna PostgreSQL Tentang Beekeeper Studio
Tidak seperti pgAdmin, Beekeeper sangat mudah digunakan tapi tetap kaya fitur–dan harganya pas! Fitur backup database-nya sangat berguna. Software yang luar biasa.
Tool yang luar biasa, IDE paling praktis yang pernah saya temukan untuk admin db Postgres dan MySql - langsung jalan, tanpa ribet :-)