我正在开始一个新项目,我在为数据库找到合适的设计时遇到了一些麻烦。
数据库域具有许多彼此相似但具有多个不同字段的实体。随着时间的推移,这些字段可能会发生变化,其中很多都是枚举。目标是以可通过管理仪表板控制字段及其可能值的方式设计数据库。
我的想法是有一个实体Super entity
存储所有实体之间的所有公共字段,有一个EntityCharacteristics
,它将实体特征与外键存储到Characteristic
表,该表将存储有关可以创建表单字段的特征的信息有了这些信息,想象一下
CharacteristicName: Age
Placeholder: Enter your age...
InputType: text
CharacteristicType: Integer
需要可以为selectbox的InputType存储可能的值,例如类似枚举的类型。此外,SuperEntity
将有一个entity_type字段,该字段将连接到EntityType
表,并且该表将连接到PossibleEntityCharacteristics
,该EntityCharacteristics
将可能的特征存储到某个实体类型。
我的问题是我应该如何将值存储在EntityCharacteristics
中,因为它们可以是不同的类型,布尔值,文本,整数,枚举等。还有我如何使用Json将可能的值存储在枚举类型中?或者使用另一个特定特征的可能值表?我如何确定https://stackoverflow.com/a/7423459中插入的值的类型是否正确并且包含枚举的可能值?
也许这是一个糟糕的设计,我不应该这样想,只是将数据存储在包含许多字段的普通表中。但是我想提供一个解决方案,可以随时轻松地更改不同类似实体的现有字段和字段值,并且不得不更改表格模式似乎不是一个好主意。我打算用PostgreSQL来实现它,它支持Json,它可能适合这里的某个地方,但由于我从未在Sql中使用过这种数据类型,所以我不知道这是不是一个好主意。
我想知道您对此的看法,我提前感谢您。
注意:我想的数据库模型就像这个JSONB
,但有点复杂,没有嵌套。
这有点基于意见,但无论如何:
我会选择一个包含所有类型对象通用属性的列的表。然后有一个额外的create table object_type
(
id integer primary key,
name text not null,
allowed_attributes jsonb not null
);
create table objects
(
id integer primary key,
name text not null,
object_type_id integer not null references object_type,
attributes jsonb
);
insert into object_type (id, name, allowed_attributes)
values
(1, 'spaceship', '{"seats": "integer", "color": "text"}'::jsonb),
(2, 'book', '{"number_of_pages": "integer", "color": "text"}'::jsonb);
insert into objects (id, name, object_type_id, attributes)
values
(1, 'Heart Of Gold', 1, '{"seats": 4, "color": "white"}'),
(2, 'H2G2', 2, '{"number_of_pages": 42, "color": "black", "published_in": 1979}');
列,用于存储可能在不同类型之间变化的各个属性。
您可以更进一步,并在第二个表中创建“类型描述”,该表定义了类型的允许属性。然后可以通过管理界面UI,您也可以使用它来验证放入基表的“动态”属性的数据。
像这样的东西:
published_in
现在在上面的例子中,object_type
是一个基于select *
from (
select *,
attributes - (select array_agg(t.k)
from object_type ot, jsonb_object_keys(ot.allowed_attributes) as t(k)
where ot.id = o.object_type_id) as invalid_attributes
from objects o
) t
where invalid_attributes <> '{}';
中相应行不允许的属性。这些行可以用例如以下查询:
json_typeof()
您甚至可以构建一个触发器,在插入或更新对象时执行此类检查。
使用object_type
函数,您还可以验证提供的键的值是否与qazxswpoi中定义的数据类型匹配