我有一个系统,该系统通过网络获取信息并将其存储在postgres数据库中。信息只有一种“种类”,因此只有一张表。让我们为这个表建模:
item: string
comment: jsonb
timestamp: datetime
有很多项目,时间戳是由一个单独的系统生成的,然后才到达具有数台服务器的Web前端。我需要做的是确保为给定的item
值插入数据库的每个记录都比上一个更新。如果它较旧,则不应将其添加到数据库中。
为澄清起见,假设有以下三种消息:
Message 1:
{time: 1,
item: "A"
}
Message 2:
{time: 3,
item: "A"
}
Message 3:
{time: 2,
item: "b"
}
如果消息以1-2-3
的顺序到达,则所有三个消息都将放入数据库中,因为消息3与消息1或2是不同的项,因此不进行比较。
如果消息以2-1-3
的顺序到达,则消息1不会放置在数据库中,因为消息2是项A
的更新消息。
我想使用数据库进行此检查,以避免不同服务器之间的竞争状况。
我一直在阅读PostgreSQL文档,但看起来我不能通过约束或排除来做到这一点。我如何让数据库在插入记录之前进行此排序检查?
答案 0 :(得分:4)
假设您的桌子看起来像这样...
create table messages (
item text not null,
comment jsonb,
created_at timestamp not null
);
您可以使用触发器来完成此操作。
create or replace function check_only_newer_messages_for_item() returns trigger as $foo$
declare max_created_at_for_item timestamp;
begin
max_created_at_for_item := (
select coalesce(max(created_at), '-infinity'::timestamp)
from messages
where item = new.item
);
if max_created_at_for_item >= new.created_at then
raise exception 'out of order message';
end if;
return new;
end;
$foo$ language plpgsql;
create trigger only_newer_messages_for_item
before insert on messages
for each row execute function check_only_newer_messages_for_item();
test=# insert into messages (item, created_at) values ('a', '2019-01-01');
INSERT 0 1
test=# insert into messages (item, created_at) values ('a', '2019-01-01');
ERROR: out of order message
CONTEXT: PL/pgSQL function check_only_newer_messages_for_item() line 10 at RAISE
test=# insert into messages (item, created_at) values ('b', '2018-01-01');
INSERT 0 1
test=# insert into messages (item, created_at) values ('b', '2018-01-02');
INSERT 0 1
test=# insert into messages (item, created_at) values ('b', '2018-01-01');
ERROR: out of order message
CONTEXT: PL/pgSQL function check_only_newer_messages_for_item() line 10 at RAISE
在item
和created_at
上的综合索引将有助于其良好运行。