如果密钥已经存在,则以增量方式插入/更新嵌套的jsonb

问题描述

我正在尝试在postgresql中创建一些API端点的日常使用日志。

我想将数据保留在嵌套的jsonb列中,以保持数据紧凑,因为我每天都不需要它。

模式如下:

CREATE TABLE clients (
  id INT,name TEXT,CONSTRAINT clients_pkey PRIMARY KEY (id)
);
INSERT INTO clients (id,name) VALUES (1,'John');
INSERT INTO clients (id,name) VALUES (2,'Mike');

CREATE TABLE client_usages (
  id INT,date DATE,usage_data JSONB,client_id INT,CONSTRAINT client_id_fk FOREIGN KEY (client_id)
        REFERENCES clients (id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE CASCADE
);

CREATE UNIQUE INDEX clint_id_date_idx
    ON client_usages USING btree
    (client_id,date);

我需要存储的数据具有client_usage.usage_data中这样的嵌套结构:

{
  controller_name: {
    action_name: {
      status_code: 1
    }
  }
}

因此,对于每个请求,我都有controller_nameaction_namestatus_code的值。

我想创建一个通用的sql调用,该调用将:

  1. 如果client_iddate的组合中不存在该记录,请插入该记录
  2. 如果记录已存在,则插入嵌套结构(如果尚未存在),计数器为1,如果存在,则将计数器增加1

例如,流程可能是:

控制器名称"SomeController",操作名称"some_action",状态代码"200"

这应该导致插入JSONB结构,如:

{
  "SomeController": {
    "some_action": {
      "200": 1
    }
  }
}

现在让我们提出另一个请求:ontroller_name:"SomeController"和action_name: "some_acion"和status_code:"200",它应该只将1增至2,结果是:

{
  "SomeController": {
    "some_action": {
      "200": 2
    }
  }
}

如果随后出现另一个请求,例如controller_name:"SomeController",action_name:"some_action",status_code:"400",则它会导致:

{
  "SomeController": {
    "some_action": {
      "200": 2,"400": 1
    }
  }
}

然后出现另一个要求,例如controller_name:"AnotherController",action_name:"some_action",status_code:"400",那么它应导致:

{
  "SomeController": {
    "some_action": {
      "200": 2,"400": 1
    }
  },"AnotherController": {
    "some_action": {
      "400": 1
    }
  }
}

最后是"AnotherController",action_name:"new_action",status_code:"200",则结果应为:

{
  "SomeController": {
    "some_action": {
      "200": 2,"AnotherController": {
    "some_action": {
      "400": 1
    },"new_action": {
      "200": 1
    }
  }
}

我认为这涵盖了所有情况

我正在考虑创建通用的INSERT语句和ON CONFLICT的{​​{1}},然后是(client_id,date)UPDATE的嵌套json。像这样:

usage_date

我的主要问题是,我无法弄清楚如何进行更新,要么创建丢失的密钥,要么将现有的密钥增加INSERT INTO client_usages (client_id,date,usage_data) VALUES(client_id,'{controller_name: {action_name: {status_code: 1}}}'::jsonb) /* where the variables of cause are replaced with real data... */ ON CONFLICT (client_id,date) DO UPDATE SET usage_data = /* this is where it get's harder.... */

在这里创建了一个小提琴:https://www.db-fiddle.com/f/476bywubxAX2x7oGNtD3cK/1

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...