如何附加到 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
然后您使用普通 INSERT
或 DELETE
添加和删除产品,不会像上述所有操作那样导致同一用户的并发写入问题。
每个用户我有 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
然后您使用普通 INSERT
或 DELETE
添加和删除产品,不会像上述所有操作那样导致同一用户的并发写入问题。