如何标记数据库中的每个表?通用外键、数组列或其他方法[关闭]

问题描述 投票:0回答:1

我目前正在设计一个 PostgreSQL 数据库,我需要在其中实现标记功能。本质上,我的数据库中许多表(7+)中的任何项目都可以通过键值标签进行标记,非常类似于 Azure 标签。

我正在考虑实现此功能的不同方法,但我对最佳方法感到困惑,因为这一定是许多数据模型中的常见问题:

  1. 使用 Django 的通用外键。

    我正在考虑的一种方法是利用 Django 的通用外键功能来创建一个通用的“标签”表,该表可以引用数据库中的任何其他表。这允许灵活性并避免复杂的逻辑。但是,可能会存在一些缺点,例如性能影响或如果没有 Django 的 ORM,数据库就没有意义。

  2. 在单个表中手动实现,无需通用外键。

    另一种选择是手动实现“Tags”表,而不依赖 Django 的通用外键。我将创建一个单独的表,可以引用数据库中的任何其他表,但不使用正式的外键。这需要在数据库或后端存储一些逻辑,维护起来更加复杂。

  3. 每个表都有单独的交叉引用标签表。

    或者,我可以为数据库中需要标记的每个表创建一个单独的表(即

    car_tags
    house_tags
    person_tags
    )。这种方法将确保清晰的分离和潜在的更好的性能,但它可能会导致冗余并增加查询和维护的复杂性。

  4. 在每个表中添加

    tags TEXT[]
    数组列。

    在每个需要标记的表中引入一个“tags”数组列,而不是维护一个通用的“Tags”表。这简化了查询,但可能会限制灵活性和可扩展性。

哪种方法最适合此用例?我更关心数据库的可维护性和可扩展性,而不是性能。如果这些不合适,您可以建议在 PostgreSQL 中实现灵活标记系统的任何最佳实践。

django postgresql foreign-keys many-to-many generic-foreign-key
1个回答
1
投票
    从数据库的角度来看,Django 的
  1. GenericForeignKey

     只是弱的、未强制/未保护的引用。 
    Tags 表将有另外两列,一列标识它所标记的
    thing
    的类型,另一列保存该事物的唯一标识符。 无论有没有 Django ORM,理解这一点都不难。这实际上是 PostgreSQL 在内部管理某些事物的方式:

    pg_class.relkind

     告诉您它列出的 
    thing 的类型,pg_class.oid 标识特定的事物。当您
    在系统视图
    information_schema
    中查找内容时,它将过滤到
    pg_class
    中列出的特定类型的内容,并在
    oid
    上加入它。
    
    

  2. 您可以轻松地自己实现此功能,就像 Django 所做的那样:
  3. 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;

    一个问题是为这些事物设置视图和联接,另一个问题是每个事物可以使用不同的、可能是多列的主键,您需要将其映射到单个通用外键引用。有些系统使用
    uuid

    作为所有事物的 pk,使每个事物的每个标识符在类型上全局唯一且统一,从而简化了这一点。 您还需要实现自己的机制来处理

    ON UPDATE
    ON DELETE
    行为 以及链接验证以避免一致性损失。
    
    
    这是标准化的方法。如果您考虑 Django 对 
    GenericForeignKey

    的作用以及您可能尝试重新实现的内容,那么这只是每个事物一个表而已:上面示例中的
  4. tag_anything
  5. 变为

    tag_cat

    ,失去了 
    thing_type
     列并获得正确的外键引用,具有足够的类型。
    您可以免费获得 
    on update
    on delete

    和一致性检查。

    到处添加
    text[]

  6. jsonb
  7. 听起来就像一场噩梦。你会在各处重复标签,并权衡每个标记的东西。基于这些的查询必须命中数据库中的每个标记表。

    
        

© www.soinside.com 2019 - 2024. All rights reserved.