Sẽ hiệu quả hơn nhiều khi lưu trữ các giá trị của bạn trong một lược đồ chuẩn hóa. Điều đó nói rằng, bạn cũng có thể làm cho nó hoạt động với thiết lập hiện tại của bạn.
Giả định
Giả sử định nghĩa bảng này:
CREATE TABLE tbl (tbl_id int, usr jsonb);
"người dùng" là một từ dành riêng và sẽ yêu cầu trích dẫn kép để được sử dụng làm tên cột. Đừng làm vậy. Tôi sử dụng usr
thay thế.
Truy vấn
Truy vấn không tầm thường như các bình luận (hiện đã bị xóa) có vẻ như:
SELECT t.tbl_id, obj.val->>'count' AS count
FROM tbl t
JOIN LATERAL jsonb_array_elements(t.usr) obj(val) ON obj.val->>'_id' = '1'
WHERE t.usr @> '[{"_id":"1"}]';
Có 3 bước cơ bản :
1. Xác định hàng đủ điều kiện với giá rẻ
WHERE t.usr @> '[{"_id":"1"}]'
xác định các hàng với đối tượng phù hợp trong mảng JSON. Biểu thức có thể sử dụng chỉ mục GIN chung trên jsonb
cột hoặc một chỉ mục với lớp toán tử chuyên biệt hơn jsonb_path_ops
:
CREATE INDEX tbl_usr_gin_idx ON tbl USING gin (usr jsonb_path_ops);
WHERE
Mệnh đề được thêm vào là hợp lý , nhưng nó được yêu cầu sử dụng chỉ mục. Biểu thức trong mệnh đề nối thực thi cùng một điều kiện nhưng chỉ sau khi hủy bỏ mảng trong mỗi hàng đủ điều kiện cho đến nay. Với hỗ trợ chỉ mục, Postgres chỉ xử lý các hàng có chứa một đối tượng đủ điều kiện để bắt đầu. Không quan trọng lắm với các bảng nhỏ, tạo ra sự khác biệt lớn với các bảng lớn và chỉ một vài hàng đủ điều kiện.
Liên quan:
2. Xác định (các) đối tượng phù hợp trong mảng
Vô duyên với jsonb_array_elements()
. ( unnest()
chỉ tốt cho các kiểu mảng Postgres.) Vì chúng tôi chỉ quan tâm đến các đối tượng thực sự khớp, hãy lọc trong điều kiện nối ngay lập tức.
Liên quan:
3. Trích xuất giá trị cho khóa lồng nhau 'count'
Sau khi các đối tượng đủ điều kiện đã được trích xuất, chỉ cần : obj.val->>'count'
.
obj(value)
đến từ đâu? Là nó trênLATERAL JOIN
,jsonb_array_elements
hoặc ở một nơi khác?