我正在尝试在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_name
,action_name
和status_code
的值。
我想创建一个通用的SQL调用,该调用将:
client_id
和date
的组合中不存在该记录,请插入该记录例如,流程可能是:
控制器名称:"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,
"400": 1
}
},
"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, date, '{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