pau*_*l23 5 postgresql database-design
在我们当前的应用程序中,我们基本上将为每个字段提供称为“翻译”的东西。所以一个表最初是这样的:
CREATE TABLE organisation (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL DEFAULT '',
)
Run Code Online (Sandbox Code Playgroud)
但是,该名称现在将取决于语言。
基本的解决方案是不再将名称字段存储在组织表中,而是存储在“organisation_language”表中:
CREATE TABLE organisation (
id SERIAL PRIMARY,
);
CREATE TABLE organisation_language
(
id SERIAL PRIMARY KEY,
organisation INTEGER NOT NULL,
field_name TEXT NOT NULL,
field_language TEXT NOT NULL,
field_translation TEXT NOT NULL DEFAULT '',
FOREIGN KEY (organisation)
REFERENCES public.organisation (id) MATCH SIMPLE
ON UPDATE CASCADE
ON DELETE CASCADE
NOT VALID
);
Run Code Online (Sandbox Code Playgroud)
(是的,我故意忽略了我可以为语言键添加查找表en-US
并参考它)。
但是,现在我不能再“保证”name
定义每个字段(如)。当然,代码可以确保它确实如此,但那是另一层。它还增加了相当多的复杂性,因为不再容易看到哪些字段甚至属于数据模型。或者为某个组织提供什么翻译。
如果我查看 JSON,我实际上会“喜欢”我的后端在请求“来自组织 1 的数据”时发送到前端,它看起来像:
{
id: 1
name: {
"en-us": 'hello world',
"nl-nl": 'hoi wereld'
}
}
Run Code Online (Sandbox Code Playgroud)
最重要的是,发生的主要操作是“插入”——然后一次插入所有数据(所以一次所有翻译),并检索所有语言数据,而不是单一语言。(由于“路径”,例如en-gb
check中不存在字段en-us
,并且此计算发生在后端)。
修改很少发生,我们甚至考虑“不支持它”,而是采用写时复制和停用旧的“组织”。
这让我想到,将“名称”字段的类型更改为 JSON 而不是语言表是一个坏主意吗?(并对所有字段执行此操作)。然后它看起来像:
CREATE TABLE organisation
(
id SERIAL PRIMARY KEY,
name JSON NOT NULL DEFAULT '{}'::JSON
);
Run Code Online (Sandbox Code Playgroud)
插入到 name 字段的数据将是(后端必须验证架构):
{
"en-us": 'hello world',
"nl-nl": 'hoi wereld'
}
Run Code Online (Sandbox Code Playgroud)
与使用语言表相比,使用 JSON 字段是否存在实际缺陷?它具有更容易查找和插入(或删除)的优点。而且由于无论如何都不应该进行修改,因此没有缺点 - 对吗?
或者 PostgreSQL 会在以后窒息吗?
第一个范式要求列是单个原子值。我认为,如果您真的将这些 JSON 对象视为存储和检索的对象,那么从数据库的角度来看它们是原子的,并且您计划执行的操作没有问题。
如果您想在条件中使用 JSON 的一部分WHERE
,那仍然没问题。如果您想要基于 JSON 部分的数据库约束,或者想要基于 JSON 属性进行连接,我建议不要使用这样的数据模型。