【问题标题】:Database function which updates json更新 json 的数据库函数
【发布时间】:2017-01-24 14:50:59
【问题描述】:

在 Postgres 数据库中,我有一个定义用户的表(用户)。就像

|ID|                    meta                               |
|01|  {"email" : "test1@gmail.com","importance" : "High"}  |
|02|  {"email" : "test2@gmail.com","importance" : "Medium"}|

正如您所见,'meta' 列包含 json,出于特定原因。 (不可更改)

我想创建一个函数,它接受 3 个参数:

  • 一封电子邮件 (inc_email)
  • 密钥 (inc_key)
  • 一个值(inc_value)

然后它将搜索具有包含电子邮件的元数据的记录,并将新的键值添加到 json 中。但!如果 value 为空,如果 key-values 已经存在,它将删除它们。

示例:

函数('test1@gmail.com','security','true')

结果:

|ID|                    meta                                                  |
|01|  {"email" : "test1@gmail.com","importance" : "High", "security":"true"}  |

然后:

function('test1@gmail.com','security','')

结果:

|ID|                    meta                             |
|01|  {"email" : "test1@gmail.com","importance" : "High"}|

到目前为止,我已经到了搜索特定记录的地步,并返回了 json 结果,但我不确定实现此 json 修改的最佳方法是什么。

declare
 ret json;
begin
  select array_to_json(array_agg(u.meta)) into ret
   from Users u
    where meta::text LIKE ('%"email" : "' || inc_email || '%');
  return ret;
end;

【问题讨论】:

    标签: database postgresql function


    【解决方案1】:
    CREATE OR REPLACE FUNCTION set_value(
       inc_email text,
       inc_key text,
       inc_value text
    ) RETURNS void LANGUAGE plpgsql AS
    $$DECLARE
       r_id integer;
       r_meta json;
    BEGIN
       /* loop through all matching rows */
       FOR r_id, r_meta IN
          SELECT id, meta
             FROM users
             WHERE meta::jsonb @> ('{ "email": "' || inc_email || '" }')::jsonb
       LOOP
          /* add, update or delete the key/value pair */
          r_meta := CASE
                       WHEN inc_value IS NULL
                          OR inc_value = ''
                       THEN
                          /* remove key/value pair */
                          (r_meta::jsonb - inc_key)::json
                       ELSE
                          /* add or replace key/value pair */
                          jsonb_set(
                             r_meta::jsonb,
                             ARRAY[inc_key],
                             ('"' || inc_value || '"')::jsonb
                          )::json
                    END;
    
          /* write the result back to the database */
          UPDATE users
             SET meta = r_meta
             WHERE id = r_id;
       END LOOP;
    END;$$;
    

    【讨论】:

    • 对我来说,他似乎并不确定“修改 jsonb”部分。
    • 没错,我感兴趣的是 json 更新,因为它似乎不是正常的“更新”,因为我不想在数据末尾连接任何值,我会喜欢用新的扩展json的内部。反正我不会做 for 循环,因为每封电子邮件都是独一无二的。
    • 我会先看这篇文章,它有一些非常详细的解释:stackoverflow.com/questions/18209625/…
    • 好吧,我放弃并为你写代码(虽然没有什么有趣或棘手的地方)。
    • 问题出在哪里?转换为jsonb,然后返回json
    猜你喜欢
    • 2011-11-29
    • 2018-02-28
    • 1970-01-01
    • 2020-01-13
    • 1970-01-01
    • 2013-11-07
    • 2020-06-22
    • 1970-01-01
    • 2020-07-08
    相关资源
    最近更新 更多