JSONB là một công cụ cực mạnh cho phép lưu trữ các cấu trúc dữ liệu phức tạp như object lồng nhau hoặc array. Nhưng chỉ lưu dữ liệu trong JSONB thì chưa đủ — mình phải biết cách lấy dữ liệu ra nữa. Ví dụ, giả sử bạn có một cột data trong bảng users, nơi lưu tất cả cài đặt của user dưới dạng JSONB. Muốn biết user chọn theme nào? Phải trích xuất nó từ JSONB-объект.
Nếu JSONB là một cái rương kho báu, thì các operators ->, ->>, #>> và các function như jsonb_extract_path() chính là chìa khóa của bạn. Cùng xem cách dùng nhé.
Các operators cơ bản để làm việc với JSONB
PostgreSQL có một vài operators chính để thao tác với JSONB. Chúng giúp lấy value từ key, object lồng nhau và array. Đây là những cái quan trọng nhất:
Operator ->
Operator -> sẽ lấy object hoặc array theo key chỉ định. Nếu bạn muốn lấy value đúng format như trong JSON, dùng operator này là chuẩn.
Ví dụ:
-- Ví dụ dữ liệu
SELECT '{"name": "Alice", "age": 25}'::jsonb -> 'name';
-- Kết quả: "Alice"
Operator ->>
Operator ->> giống ->, nhưng nó trả về value dạng text. Rất tiện khi bạn chỉ cần lấy dữ liệu dạng chuỗi đơn giản.
Ví dụ:
-- Ví dụ dữ liệu
SELECT '{"name": "Alice", "age": 25}'::jsonb ->> 'age';
-- Kết quả: "25" (chuỗi)
Operator #>>
Operator #>> dùng để lấy dữ liệu từ object lồng nhau theo đường dẫn chỉ định. Đường dẫn truyền vào là một array các key.
Ví dụ:
-- Ví dụ dữ liệu
SELECT '{"user": {"name": "Bob", "details": {"age": 30}}}'::jsonb #>> '{user, details, age}';
-- Kết quả: "30" (chuỗi)
Khác biệt giữa -> và ->>:
Nếu bạn muốn giữ nguyên kiểu dữ liệu (ví dụ array hoặc object), dùng ->. Nếu chỉ cần text, dùng ->> nhé.
Dùng function để thao tác với JSONB
Function jsonb_extract_path() sẽ lấy value từ JSONB-объект theo đường dẫn chỉ định. Nó giống operator #>> nhưng nhìn code sẽ rõ ràng hơn chút.
Ví dụ:
SELECT jsonb_extract_path('{"user": {"name": "Alice", "settings": {"theme": "dark"}}}'::jsonb, 'user', 'settings', 'theme');
-- Kết quả: "dark"
Nếu bạn muốn lấy luôn value dạng text, dùng jsonb_extract_path_text(). Nó hoạt động giống jsonb_extract_path() nhưng trả về chuỗi.
Ví dụ:
SELECT jsonb_extract_path_text('{"user": {"name": "Alice", "settings": {"theme": "dark"}}}'::jsonb, 'user', 'settings', 'theme');
-- Kết quả: dark
Ví dụ thực tế
Lấy value theo key. Giả sử mình có bảng products, cột details lưu dữ liệu dạng JSONB:
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name TEXT,
details JSONB
);
INSERT INTO products (name, details) VALUES
('Laptop', '{"brand": "Dell", "price": 1200, "specs": {"ram": "16GB", "cpu": "Intel i7"}}'),
('Phone', '{"brand": "Apple", "price": 1000, "specs": {"ram": "4GB", "cpu": "A13"}}');
Kết quả:
| id | name | details |
|---|---|---|
| 1 | Laptop | {"brand": "Dell", "price": 1200, "specs": {"ram": "16GB", "cpu": "Intel i7"}} |
| 2 | Phone | {"brand": "Apple", "price": 1000, "specs": {"ram": "4GB", "cpu": "A13"}} |
Lấy brand của tất cả sản phẩm.
SELECT name, details->'brand' AS brand FROM products;
Kết quả:
| name | brand |
|---|---|
| Laptop | "Dell" |
| Phone | "Apple" |
Lấy value dạng text. Nếu muốn brand không có dấu ngoặc kép, dùng operator ->>:
SELECT name, details->>'brand' AS brand FROM products;
Kết quả:
| name | brand |
|---|---|
| Laptop | Dell |
| Phone | Apple |
Lấy dữ liệu lồng nhau. Lấy dung lượng ram (ram) cho từng sản phẩm:
SELECT name, details#>>'{specs, ram}' AS ram FROM products;
Kết quả:
| name | ram |
|---|---|
| Laptop | 16GB |
| Phone | 4GB |
Lấy dữ liệu theo đường dẫn. Cũng có thể dùng function jsonb_extract_path_text() để làm tương tự:
SELECT name, jsonb_extract_path_text(details, 'specs', 'ram') AS ram FROM products;
Kết quả:
| name | ram |
|---|---|
| Laptop | 16GB |
| Phone | 4GB |
Lỗi thường gặp và cách tránh
Lỗi hay gặp nhất là khi bạn:
- Cố lấy dữ liệu theo đường dẫn sai. Ví dụ, nếu key không tồn tại thì kết quả sẽ là
null. - Dùng sai operator cho mục đích.
->hợp cho object và array, còn lấy text thì phải dùng->>.
Ví dụ lỗi:
-- Lỗi: không có key 'nonexistent'
SELECT details->>'nonexistent' FROM products;
-- Kết quả: null
Tip: luôn kiểm tra cấu trúc dữ liệu trước khi viết query để tránh lỗi nhé.
Ứng dụng thực tế
Trích xuất dữ liệu từ JSONB được dùng rất nhiều trong các app thực tế:
- Trong e-commerce để xử lý thuộc tính sản phẩm.
- Trong web app để lưu cài đặt user.
- Trong analytics để xử lý dữ liệu có cấu trúc như event và log.
Thêm một ví dụ nữa. Giả sử có bảng orders lưu dữ liệu về đơn hàng:
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
customer_name TEXT,
items JSONB
);
INSERT INTO orders (customer_name, items) VALUES
('John', '[{"product": "Laptop", "quantity": 1}, {"product": "Mouse", "quantity": 2}]'),
('Alice', '[{"product": "Phone", "quantity": 1}]');
Lấy tên tất cả sản phẩm trong các đơn hàng:
SELECT customer_name, jsonb_array_elements(items)->>'product' AS product FROM orders;
Kết quả:
| customer_name | product |
|---|---|
| John | Laptop |
| John | Mouse |
| Alice | Phone |
Tiếp theo tụi mình sẽ đi sâu hơn vào JSONB, khám phá dữ liệu lồng nhau và chuyển đổi nó thành dạng dễ phân tích hơn. Chuẩn bị sẵn sàng cho nhiều điều thú vị nữa nhé!
GO TO FULL VERSION