我目前正在设计一个 PostgreSQL 数据库,我需要在其中实现标记功能。本质上,我的数据库中任何表中的任何项目都可以通过键值标签进行标记,非常类似于 Azure 标签。
我正在考虑实现此功能的不同方法,但我对最佳方法感到困惑:
car_tags
、house_tags
、person_tags
)。这种方法将确保清晰的分离和潜在的更好的性能,但它可能会导致冗余并增加查询和维护的复杂性。tags TEXT[]
数组列:哪种方法最适合此用例?我更关心数据库的可维护性和可扩展性,而不是性能。 如果这些不合适,您可以建议在 PostgreSQL 中实现灵活标记系统的任何最佳实践。
Django 的通用外键只是弱的、未强制/未保护的引用。
Tags
表将有另外两列,一列标识它所标记的 thing 的类型,另一列保存该事物的唯一标识符。
无论有没有 Django ORM,从中找出头绪或尾部应该不会太难。这实际上是 PostgreSQL 在内部管理某些事物的方式:
pg_class.relkind
告诉您它列出的 thing 的类型,pg_class.oid
标识特定的事物。当您在系统目录和视图中查找内容时,它将过滤到 pg_class
中保存的特定关系类型,并在 oid
上加入它。
您可以轻松地自己实现此功能,就像 Django 所做的那样:
create table tag (
id bigint generated by default as identity primary key,
name text);
create table tag_anything (
tag_id bigint references tag(id),
other_thing_type text,
other_thing_id text);
create view cat_tagged as
select cat.*,array_agg(tag.name) as tags
from cat
join tag_anything ta
on ta.other_thing_type='cat'
and ta.other_thing_id=cat.id
join tag
on tag.id=ta.tag_id;
group by cat.id;
一个问题是为这些事物设置视图和联接,另一个问题是每个“事物”可以使用不同的、可能是多列的主键,您需要将其映射到单个通用外键引用。
tag_anything
变为
tag_cat
,丢失 thing_type
列并获得正确的外键引用,具有适当的类型。
text[]
或
jsonb
听起来就像一场噩梦。你会在各处重复标签并加重一切负担。