如何附加到 json 列中给定键的值?

How to append to the value of a given key in a json column?

每个用户我有 user_product_mapping 个存储产品:

DROP TABLE IF EXISTS user_product_mapping;
CREATE TABLE user_product_mapping 
(
    id SERIAL NOT NULL PRIMARY KEY,
    user_id INT,
    product_info json NOT NULL,
    CONSTRAINT fk_user FOREIGN KEY(user_id) REFERENCES users(user_id)
);

示例值:

INSERT INTO user_product_mapping (user_id, product_info)
VALUES
(1, '{"product": "laptop,mobile"}'),
(2, '{"product": "charger"}'),
(3, '{"product": "mobile,mouse,charger"}')
;

现在我想将新产品添加为 'laptop' 到现有的 user_id 2.
预期结果:

user_id | product_info
---------------------------------------
      2 | {"product": "charger,laptop"}

我尝试追加但遇到问题:

UPDATE user_product_mapping
SET product_info = product_info || '{"laptop"}'
WHERE user_id = 2;

Error: 
ERROR:  column "product_info" is of type json but expression is of type text
LINE 2: SET product_info = product_info || '{"123e4567-e89b-12d3-a45...
                           ^
HINT:  You will need to rewrite or cast the expression.

能否请您提出前进的方向。

UPDATE user_product_mapping
SET    product_info = json_build_object('product', concat_ws(',', NULLIF(product_info->>'product', ''), 'laptop'))
WHERE  user_id = 2;

即使缺少 'product' 键、具有空值的键或空列表也能正常工作。不过是给猪涂口红

它最终会提取文本值,将另一个项目连接到列表(安全地),并分配一个新包装的 JSON 值。参见:

  • How to concatenate columns in a Postgres SELECT?

在使用 JSON 时,data type jsonb would be more practical, so you can use jsonb_set():

SET    product_info = jsonb_set (product_info, '{product}', to_jsonb(concat_ws(',', NULLIF(product_info->>'product', ''), 'laptop')))

更实用的是,使用 JSON 数组而不是文本值列表。

SET    product_info = product_info || jsonb '"laptop"'

作为 Postgres 文本数组,这会更实用:text[],然而。

SET    product_info = product_info || 'laptop'

但您可能真正应该做的是正确规范化的 many-to-many 实现:

  • How to implement a many-to-many relationship in PostgreSQL?
  • How to perform update operations on columns of type JSONB in Postgres 9.4

然后您使用普通 INSERTDELETE 添加和删除产品,不会像上述所有操作那样导致同一用户的并发写入问题。