学到更多
请记住,您将拥有使用 SQL 管理数据库的完全访问权限。 Directus 将反映任何更改。 您还可以通过 API 以编程方式配置数据模型。 要了解更多信息,请参阅我们关于 Collections、Fields 和 Relations 的 API 文档。
关系数据模型
为了了解 Directus 如何处理数据模型,您需要了解什么是关系数据模型。本节简要总结了核心概念。它可能作为评论有用,或者对于在您的团队中工作的想要简单解释数据模型如何工作的业务用户可能很有用。如果您对关系数据模型概念有扎实的了解,例如数据库、数据表、列、数据类型、主键和外键、行、关系和模式,那么请随意跳转到 [Directus 中的数据模型](#data -模型直接)。
数据库
Directus 是一个 SQL 数据库包装器。数据库是以结构化方式存储在计算机中的一组数据,使其具有组织性、可访问性和可扩展性。在数据库中构建数据的特定方式称为数据模型。
数据库与 Excel
为了进行大多数业务用户可以进行的比较,将数据存储在数据库中_有点_类似于将数据存储在 Excel 电子表格中。您知道如何在 Excel 的一个工作表上构建一个表格,在另一个工作表上构建另一个表格,然后将每个表格的行链接在一起吗?这几乎就是关系数据模型的工作原理。但是 Excel 和关系数据库在一些关键点上有所不同。
很多时候,我们将数据作为表格存储在 Excel 中,但情况并非总是如此,因为该程序有很多其他用途。 Excel 可以让您的数据风格化_(粗体、斜体、彩色、自定义字体等)_,在单元格中设置动态函数,添加图表和图形等图形,并将任何类型的数据输入到您想要的任何单元格中没有强制结构。您的 Excel 电子表格是一块空白画布,旨在存储多达数万行的信息。
数据库中没有程式化。它们以结构化的方式严格存储原始数据值。任何时候您想要设置数据样式、构建函数、将数据放入图表等等,您都必须在您的应用程序或网站中创建该功能。数据库存储原始的、非程式化的结构化数据,旨在处理数百万行,在某些情况下是数十亿甚至数万亿行信息。
数据表
SQL 数据库跨数据表存储数据。数据表通常存储有关一种不同类型的记录、对象或观察的信息,例如金融交易、博客文章、地理位置、用户、物联网事件,或任何东西。数据表进一步细分为列和行。
列
列是存储一种信息的类别。每列都有一个唯一的描述性名称,并在其每个 单元格值 中存储一个信息单元。列使数据保持井井有条、一致且易于访问。您选择添加到数据表中的列将完全取决于您需要存储的信息。
例如,在物联网设备监控天气的数据库中,iot_events
数据表可能包含列 device_id
、location
、time
、temperature
、pressure
、humanity
、等等
单元格值
列中的每个值都存储在其自己的单元格中。通常,您希望创建保存 atomic 值的列。这意味着创建列以存储最小的不可分割单元。列中包含的信息种类没有限制,但有好的和坏的做法。例如:
- 错误的列:
city_state_zipcode
列。 - 正确的列: 单独的
city
、state
和zipcode
列。
数据类型
为了进一步保持结构和一致性,在创建列时,还必须定义其数据类型。例如,“age”列可能被分配“INTEGER”,“blog_content”列可能被分配“STRING”或“TEXT”数据类型。当程序尝试处理具有错误数据类型的数据时,可能会出现无数不一致、意外和潜在危险的行为。
举个例子,如果你输入字符“2”,它可能被存储为“INTEGER”或“STRING”。如果您将 2
存储为 INTEGER
,当您尝试添加 2 + 2
时,计算机通常会计算 4
。在某些语言中,如果您将字符 "2"
存储为 STRING
,当您尝试添加 "2" + "2"
时,计算机会将它们连接成 22
,而在其他语言中,尝试这样做可能会使程序崩溃!
因此,当您使用数据时,了解它的数据类型是很重要的,因为错误的数据类型可能会在您的程序中导致意外甚至危险的行为。
行
每行存储与唯一记录、事件、对象、实体、观察等相关联的数据。数据表可以包含数百万、甚至数十亿和数万亿行数据。
主键
为了唯一标识和跟踪每一行,每个数据表都必须有一个主键列。主键是标识特定行的唯一 ID。任何模式或系统都可以用来生成主键,只要它保证每个键都是唯一的。也许最常见的是递增整数,其中每个新行上的主键递增如下 1
、2
、3
、4
等...主键列保证您始终可以找到一行并将其与其他行区分开来。
外键
由于主键唯一标识数据表中的每一行,因此它们是创建关系的完美工具。如果您想在两个数据表之间建立关系链接行,您可以创建一个列来存储_外键_,它们只是来自外部表的主键。这称为_外键列_,表示它存储来自外部表的键。
父级与相关表
当我们谈论两个相关表时,我们将它们称为_父表_和_相关表_。这两个术语仅基于透视,类似于术语 this 和 that 或术语 here 和 there,表示您从哪个角度看待关系。
例如,在数据模型中,多对一关系 与 一对多关系 相同,使用的术语仅取决于您将哪个集合视为父集合。
关系类型
有几种方法可以关联地链接表:
- 一对一 - 父数据表中的每一行都可以链接到相关表中的一行 (max)。
- 多对一 - 父数据表中的许多行可以链接到相关表中的一行。
- 一对多 - 数据表中的每一行都可以链接到另一个数据表中的许多行。 注意:在数据模型中,多对一和一对多关系是相同的。命名差异是一个视角问题。
- 多对多 - 父表中的许多行可以链接到相关表中的许多行。 M2M 关系需要第三个表,称为联结表。 M2M 只不过是存储在连接表上的 O2M 和 M2O。
- 多对任意 - 数据表中的许多行可以链接到数据库中任何其他表中的许多行。与 M2M 关系类似,M2A 需要一个联结数据表以及联结表上的附加列来存储相关表的名称。
要详细了解这些关系在概念上的工作方式以及它们在 Directus 中的处理方式,请参阅我们的 关系 指南。
数据库模式
到目前为止,在我们的示例中,我们已经看到并描述了实际的 数据表。在设计关系数据模型时,您需要创建一个模式来跟踪其复杂性。
模式是数据模型的蓝图,它定义了数据表、每个表中的列、每个列的详细信息以及表之间的关系。它不包括存储的实际数据点。这是两个关系链接表的简单模式:
table_one
- column1 (primary key)
- column2 (data type, optionally explain what the column stores)
- column3 (...)
table_two
- column1 (primary key)
- column2 (...)
- column3 (...)
- table_one_id (foreign key, relationally links rows via table_one.column1)
在上面的模式中,我们定义了两个具有明显通用名称的表 table_one
、table_two
和 column1
、column2
等。您为数据表和列选择的名称取决于您。理想情况下,您应该选择唯一的、容易记住的名称来标识其中存储的数据内容。
在本文档中,我们以两种方式改变了传统数据库模式的规则。首先,我们有时会添加对列是什么的完整解释。请注意,在 table_one.column2
中,在列名 (data type, optional....
在我们的示例中,如果表中存在列,但其数据类型或其他详细信息与当前学习点无关,我们将省略它们的详细信息,以便您可以专注于重要的列。
还请注意,对于更复杂的模式,包含数十个 (或数百个!) 的关系链接数据表,您通常包括数据类型信息以及每个表如何相互链接的可视化。
避免数据重复
关系数据库允许我们构建避免数据重复的数据模型,换句话说,当您将相同的数据存储在数据库的多个位置时。数据复制既低效又危险。
举个例子,让我们考虑一个“博客”表。在博客中,您可能希望显示作者的详细信息,因此您添加了一个“作者姓名”列。
blog
- id
- title
- content
- author_name (string, stores author's full name)
上表将作者姓名直接存储在“博客”数据表中。 然而,让我们想象一下,随着我们的博客文章,我们想要显示更多关于作者的信息,例如他们的电子邮件地址、社交媒体等。我们_可以_将此作者信息放入“博客”数据表中。
blog
- id
- title
- content
- author_name (string, stores author's full name)
- author_email (string, stores author's email)
- author_img (string, stores link to author's profile picture)
您可能开始注意到这个数据表不再代表一个对象,而是两个:博客文章和作者。这_几乎总是_表明数据应该在不同的表中拆分并进行关系链接。
现在让我们也假设作者是一种用户。所有用户详细信息都存储在“用户”数据表中,其数据显示在每个用户个人资料页面上,用于聊天消息和其他类型的交易,这是许多项目中的常见情况。在这种情况下,作者姓名和其他详细信息也需要存在于“用户”表中。
这会创建重复数据。这有两个大问题:
首先,保持准确的信息变得困难或不可能。如果作者决定在“用户”下更改他们的社交媒体信息,则必须有人检查并更新包含其博客文章的每一行的作者详细信息。只有 10 甚至 100 篇博客文章,这会很烦人,但也许不是一个大问题。然而,随着数据量增长到数百万或数十亿行,更新重复数据成为一个严重的问题。
此外,作者姓名和个人信息的错误可能不是真正危险的情况,但在包含银行交易或医疗记录的数据表中,不准确的信息将是灾难性的!
其次,它浪费存储空间并降低性能。对于包含数百篇博客文章的数据模型,重复数据可能不会占用足够的空间而导致性能大幅下降。但是同样,如果您在数百万或数十亿行中一次又一次地重复相同的信息,那么存储空间就会被大规模浪费。
为什么我们使用关系数据模型
如上一节所示,您希望确保每个数据点都是唯一的。 这就是关系数据模型的 relational 部分发挥作用的地方。 为避免数据重复,最好的做法是 规范化您的数据模型,这是用于描述设计数据模型的技术术语,以便 完全 不存储重复信息。 与将给定情况下所需的所有信息存储在一个表中不同,就像我们在上面混合博客和作者信息时看到的那样,数据库规范化是将这些信息拆分到多个表并将它们相关地链接在一起的过程,这样信息就不会重复 .
要掌握数据库规范化还有很多东西要学,实践中的彻底教育超出了本文档的范围。网上有很多资源可以了解它。但是,为了提供一个简单的示例,通过改进上一个 避免数据重复 部分中提供的示例 blog
数据表:
blog
- id
- title
- content
- author_name
- author_email
- author_img
如 行 部分所述,我们希望数据表中的每一行代表一个唯一的记录、事件、对象、实体、观察等。为此,我们可以 从 blog
表中删除 author_name
列并将其替换为 author_id
外键表,该表存储来自 users
表的外键。
blog
- id
- title
- content
- author_id (stores foreign key from users.id)
users
- id
- name
- email
- role
- email
- twitter
注意区别。之前我们把作者的名字直接放到了blog
数据表的一列_(创建重复数据)_中。在这里,我们将 author_name
、author_email
和 author_img
替换为 author_id
列,其中包含来自 users
的外键。从这里,我们可以使用外键在 blog
和 users
之间建立关系链接数据。
使用关系数据模型
一旦您从概念上设计了数据模型,您通常会使用 SQL 或结构化查询语言来构建它并与之交互。该语言用于创建、读取和查询、更新和删除数据库中的任何内容。
一旦设计并构建了初始数据表,下一步通常是使用 Node.js 或 Flask 等工具构建后端。 在您的后端,您必须编写自定义 API 端点和逻辑来为您的特定数据模型创建、读取、查询、更新和删除数据。 然而,当后端访问数据时,它仍然是原始的,没有程式化。 原始数据对于计算机来说很容易处理,但对于人类来说通常很难处理。
对于那些不熟悉的人来说,SQL 语言、原始数据和传统的关系数据库术语可能会让人觉得不直观且过于技术化。
教团队中的每个人如何处理和思考原始数据可能不切实际。在某些情况下,业务用户可能会发现处理原始数据很困难或几乎不可能。人们习惯于看到_彩色、程式化、嵌入在地图上的信息等,例如 大多数人在大多数情况下 会发现在地图上使用精确点很容易,但几乎不可能在地图上识别位置来自存储为 JSON 的原始纬度和经度点的世界地图。
{
"location": {
"lat": 36.088010,
"lng": 120.379771
}
}
因此,开发人员需要构建具有精美 UI 和自定义显示逻辑的前端,以使处理数据更人性化。 然而,即使对于具有强大 SQL 数据库技能的开发人员来说,构建 API 和 GUI 来构建和管理数据模型也是耗时的。
Directus 中的数据模型
上面列出的所有关系数据模型概念都适用于 Directus。您将获得完整的、独立的、关系数据模型设计和配置。不同之处在于 Directus 处理所有 SQL,构建 API,并提供 Data Studio,让业务用户以人性化的方式处理数据。
Data Studio 还提供了直观地显示数据并与之交互的特性和功能。配置数据模型后,可以通过其他 modules 访问数据。
数据模型配置发生在以下页面和菜单中:
设置 > 数据模型 > 集合 > 字段 > 字段配置抽屉 > 部分
您无需一行代码或 SQL 即可执行以下操作:
- 查看、配置和管理您的关系数据模型和资产存储。
- 配置数据在 Data Studio 中的显示方式。
- 在数据洞察中配置用户与数据交互的方式。
- 将 Data Studio 中的所有文本翻译成任何语言。
Directus 用更用户友好的术语和概念取代了传统的关系数据库术语。请记住,虽然传统的关系数据库术语严格包含数据库概念,但一些新的 Directus 术语包含这些关系数据库概念 加上显示和交互逻辑。以下部分将介绍 Directus 术语并将它们映射到经典的关系数据库概念。
集合
集合 是一组 items。这可以是与 SQL 中的数据表、一组其他集合或只读视图的 1-1 匹配。
您可以在 Settings > Data Model 下访问所有集合,包括为项目提供动力所需的内置系统集合。从那里,单击一个集合以打开其配置页面。要了解更多信息,请参阅我们的 collections 指南。
字段
字段是数据库列,但有所不同。
请记住,SQL 数据库列存储纯粹的原始数据。从那里,开发人员构建自定义逻辑和 UI 以确定如何显示这些数据并与之交互。在 Directus 中,字段包括列配置,以及关于如何在 Data Studio 中显示和交互数据的自定义配置。 Directus 还具有 别名字段,它们是虚拟的,不直接与列匹配。要了解更多信息,请参阅我们关于 字段 的指南。
项目
项目是数据表行,但有一点不同。
请记住,从我们上面关于传统数据库的讨论中,理想的关系数据库是_规范化_。 不幸的是,规范化的数据并不总是人们最容易想象或想象的,因为相关数据分布在多个数据表中。 因此,当您访问一个项目时,您可能获得的不仅仅是当前集合的行级数据,在某些情况下,一个项目可能会提供对相关行中数据的访问。
您可以从其他应用模块访问项目,例如 内容、用户目录 和 文件库。
数据类型超集
Directus 使用 数据类型超集 抽象 SQL 供应商之间的类型差异。
密钥和 ID
在 Directus 中,主键经常被称为 ID。 当您创建集合 时,您必须添加一个 id
字段。 Directus 支持以下类型的 ID:
- Auto-Incremented Integer - ID 递增
1
、2
、3
到2^31-1
或2,147,483,647
。 - Auto-Incremented Big Integer - ID 将
1
、2
、3
增加到2^63-1
或9,223,372,036,854,775,807
。 (仅在 MySQL 和 PostgreSQL 中可用) - 生成的 UUID - 通用唯一标识符。 创建一个完全唯一的 ID。 使用此系统生成的 ID (不仅在您的数据库中,而且在使用该系统的任何地方) 在统计上不太可能被重复,以至于出于所有实际目的,它们都是独一无二的。
- 手动输入的字符串 - 您手动输入一个唯一的字符串作为每个项目的 ID。
关系
Directus 支持所有标准的关系类型,以及一些自己的复合类型。 要了解更多信息,请参阅我们的 relationships 指南。