PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Cập nhật mảng JSONB cho phần tử cụ thể

PostgreSQL 11+

Nếu bạn đã ở PostgreSQL phiên bản 11 (vì mới JSONB hỗ trợ chuyển đổi loại ) đặt cược tốt nhất của bạn có lẽ là một hàm tùy chỉnh được viết bằng Perl hoặc Python.

Vì tôi ủng hộ Python 3, đây là một ví dụ chức năng:

CREATE OR REPLACE FUNCTION jsonb_replace_in_array (val jsonb, path_to_array text[], replacement jsonb, entry_filters jsonb)
    RETURNS jsonb
    TRANSFORM FOR TYPE jsonb
    LANGUAGE plpython3u
AS $$
v_new = val
tmp = v_new
for e in path_to_array:
    tmp = tmp[e]

for item in tmp:
    if (entry_filters is None or entry_filters.items() <= item.items()):
        item.update(replacement)

return v_new
$$;

... sau đó có thể được sử dụng như sau:

UPDATE configuration
SET
  config = jsonb_replace_in_array(
    config,
    '{data}',
    '{"value":"changed"}'::jsonb,
    '{"oid":"11.5.15.1.4","instance":"1.1.4"}'::jsonb
  )
WHERE config->'data' @> '[{"oid":"11.5.15.1.4","instance":"1.1.4"}]';

Vì vậy, có, điều kiện được sao chép, nhưng chỉ để giới hạn số lượng hàng phải chạm vào ngay từ đầu.

Để thực sự hoạt động khi cài đặt PostgreSQL 11 đơn giản, bạn cần có phần mở rộng plpython3ujsonb_plpython3u :

CREATE EXTENSION plpython3u;
CREATE EXTENSION jsonb_plpython3u;

Logic Python được giải thích:

for e in path_to_array:
    tmp = tmp[e]

... đưa chúng ta đến mảng các mục nhập mà chúng ta cần xem xét.

for item in tmp:
    if (entry_filters is None or entry_filters.items() <= item.items()):
        item.update(replacement)

... đối với mỗi mục trong mảng, chúng tôi kiểm tra xem tiêu chí bộ lọc có null hay không (entry_filters is None =khớp với bất kỳ mục nhập nào) hoặc mục nhập "chứa" ví dụ được cung cấp bao gồm các khóa và giá trị (entry_filters.items() <= item.items() ).

Nếu mục nhập khớp, hãy ghi đè / thêm nội dung bằng mục thay thế được cung cấp.

Tôi hy vọng điều đó sẽ đi đúng hướng mà bạn đang tìm kiếm.

Nhìn vào các khả năng hiện tại của PostgreSQL liên quan đến sửa đổi JSON, nó sẽ rất phức tạp (nếu không muốn nói là phức tạp) và cần rất nhiều chi phí để làm điều tương tự với SQL thuần túy.

PostgreSQL 9.6+

Trong trường hợp bạn chưa có sẵn phiên bản 11, hàm sau sẽ thực hiện tương tự với chi phí là tự xử lý các chuyển đổi kiểu nhưng giữ cho nó hoàn toàn tương thích với API, vì vậy khi bạn nâng cấp, điều duy nhất bạn phải làm là thay thế hàm (không cần thay đổi bất kỳ câu lệnh nào sử dụng hàm này):

CREATE OR REPLACE FUNCTION jsonb_replace_in_array (val jsonb, path_to_array text[], replacement jsonb, entry_filters jsonb)
    RETURNS jsonb
    LANGUAGE plpython3u
AS $$
import json

v_new = json.loads(val)
t_replace = json.loads(replacement)
t_filters = json.loads(entry_filters)
tmp = v_new
for e in path_to_array:
    tmp = tmp[e]

for item in tmp:
    if (entry_filters is None or t_filters.items() <= item.items()):
        item.update(t_replace)

return json.dumps(v_new)
$$;



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Quản lý một Bản cam kết PostgreSQL

  2. Các truy vấn được tham số hóa với psycopg2 / Python DB-API và PostgreSQL

  3. order_by trên trường Nhiều-Nhiều dẫn đến các mục nhập trùng lặp trong bộ truy vấn

  4. Tạo một ứng dụng nhiều người thuê bằng các lược đồ và Rails của PostgreSQL

  5. pg-promise:sử dụng kết quả của một truy vấn trong truy vấn tiếp theo trong một giao dịch