关系 Relationships

关系是任何关系数据库的关键部分。 Directus 支持所有标准关系类型,以及更多自己的_compound_ 类型,这些类型经过定制,使某些_common 但复杂_ 任务变得轻而易举。

开始之前
无论您要配置何种关系,我们建议您按顺序阅读本文档的每个部分,至少一次。这是因为您必须了解 M2O 在 Directus 中如何工作才能了解 O2M,您必须了解 M2O 和 O2M 才能了解 M2M,等等。

概述

Data Studio 通过提供无代码配置,使配置关系数据模型的过程变得更容易、更快、更直观。 Directus 对您的数据模型强制执行自以为是的模式、规则系统或其他任意限制。因此,除了项目基础架构的任何技术限制或任何关系数据模型的核心要求,比如为每个集合都有一个主键字段或为每个字段分配一个数据类型, 您可以根据需要自由构建数据模型.

在本指南中,我们将讨论以下主题:

  • Directus 中存在哪些类型的关系。
  • 如何在 Data Studio 中配置所需的关系。
  • 如何在数据模型中实现关系并在 Data Studio 中显示。
  • 何时可能适合使用给定类型的关系。

最后,您将了解开始在 Directus 中构建数据模型所需的一切,即使关系数据模型概念对您来说是一个新概念。

Directus 与经典数据模型术语

当我们使用经典的数据模型术语时,如数据表、列、行等...... 这表明解释严格集中在数据库中发生的事情上。当使用 Directus 术语时,如集合、字段、项目等...... 这表明解释包括 Directus 逻辑和功能。

多对一 (M2O)

在 M2O 关系中,父集合中的多个项目链接到相关集合中的一个项目。 例如,一个国家有很多城市,但一个城市只能在一个国家。

为了创建 M2O 关系,我们向父集合添加一个外键字段,它将父集合中的项目链接到相关集合中的项目。 如果我们有两个表,citiescountries,我们可以创建一个 cities.country_id 外键字段。

多对一关系图

让我们看一下架构。

cities
- id
- name
- country_id (外键字段,存储来自 countries.id 的键)
countries
- id
- name

请注意上述架构中的以下内容:

  • M2O 关系只需要父表中的一列。
  • 在 Directus 中配置 M2O 关系字段时,父集合上的项目页面将允许访问相关集合中的项目。 因此,在我们上面的示例中,cities 中的项目页面将允许从 countries 表访问相关国家。

但是,在 Directus Data Studio 中,M2O 字段不会自动提供对相关集合中父集合项目的访问。 在我们的示例中,这意味着当您在“国家/地区”中打开项目页面时,您将看不到相关城市。

这就是 O2M 领域发挥作用的地方。

配置 M2O
配置 M2O 字段的最简单方法是遵循如何创建字段(标准)的指南并从 模板向导。

一对多 (O2M)

在关系数据库中,O2M 关系与 M2O 的关系类型完全相同。 请记住,在 M2O 部分的末尾,我们了解到在 Directus 中配置 M2O 不允许我们访问相关集合上的项目页面中的相关项目。 在 Directus 中,配置 O2M 会创建一个 Alias 字段,让我们可以访问相关项目。 为了证明这一点,让我们继续使用 M2O 部分中使用的“城市”和“国家”示例关系。

一对多关系图

让我们看一下架构。

countries
- id
- name
- cities
  (O2M 别名字段,在数据表中不存在。 允许访问与一个国家/地区相关联的所有城市。)
cities
- id
- name
- country_id (the M2O field)

请注意上述架构中的以下几点。 当我们在 Directus 中创建 O2M 时:

  • 由于视角被翻转,我们现在将“国家”视为父集合。
  • 创建 O2M 并不总是必要的。 在某些情况下,您不希望或不需要从双方访问项目。
  • 乍一看,这个 O2M 别名字段可能会 看起来和感觉 就像创建了一个新列,但 O2M 字段是纯粹的 虚拟。 它在 Data Studio 中创建一个界面,以从 O2M 角度访问项目。 换句话说,O2M 别名字段允许我们从“国家”集合中的项目详细信息页面中的“城市”访问任何相关项目。

配置 O2M
配置 O2M 的最简单方法是遵循有关如何 创建字段(标准)的指南并从模板向导。

一对一 (O2O)

Directus 不包括专用的一对一 (O2O) 关系类型或接口。但是,在数据库中,O2O 与 M2O 几乎完全一样。唯一的区别是 O2O 强制执行 cardinality。换句话说,父集合中的一项可以与相关集合中的一项链接,反之亦然。

例如,每个国家都有一个首都,反之亦然。这是一个O2O。为了演示它是如何工作的,让我们将此 O2O 添加到前面部分中使用的“城市”和“国家”示例关系中。

您可能会想到的第一个策略是在 countries 集合上添加一个新的 capital_city 字段,直接存储首都的名称。但这会产生重复数据,因为同一个城市会同时存在于countries.capital_citycities.name中。但请记住,我们要 避免重复数据!

首都城市的重复数据

相反,我们想使用 O2O 关系。让我们尝试添加一个 cities.capital_of 字段。

低效的一对一关系

让我们看一下架构。

cities
- id
- name
- country_id
- capital_of
  (O2O字段。 实际上是一个 M2O,配置为存储唯一值,存储来自 countries.id 的外键)
countries
- id
- name
- cities

上述模式中的 O2O 关系有效,在某些情况下,将 O2O 配置到哪个集合上可能并不重要。 但在这种情况下,它是次优的。 由于 大多数城市 不是首府城市,该列将主要包含“NULL”值。 但是,每个国家都有首都。 所以如果我们在countries集合上创建O2O,效率会高很多。

A One-to-One Relationship

让我们看一下架构。

countries
- id
- name
- cities
- capital_city
  (O2O字段,实际上是一个 M2O,配置为存储唯一值,存储来自 citys.id 的外键)
cities
- id
- name
- country_id

请注意上述架构中的以下几点。 当我们在 Directus 中创建 O2O 时:

  • 我们可以在任一集合上添加 O2O 字段。 但是,在某些情况下,将其添加到特定集合中会更有效。
  • 由于O2O字段实际上只是幕后的M2O字段,并且由于Directus不会自动显示相关集合中的M2O字段,您可能需要配置一个O2M字段 这样您也可以访问相关集合中的项目。

配置O2O\

配置 O2O 的最简单方法是遵循如何创建字段(标准)的指南并选择M2O 模板向导中的字段类型。 然后,配置字段的架构,打开唯一,这样M2O字段中的每个值都是唯一的,从而形成O2O关系。

多对多 (M2M)

到目前为止我们看到的关系类型只需要一个外键列来链接父集合和相关集合。 M2M 关系由 由两个外键列 组成,存储在一个名为 junction table 的附加表中,该表存储父表和相关表之间的每个链接行。

M2M 关系中需要连接表,因为创建的关系数可能 (而且通常会!) 超过任一数据表中的行数。换句话说,如果父列中有“x”行,相关列中有“y”行,则需要空间来存储最多“x * y”行。联结表提供了一个存储行之间所有关系的地方,无论存在多少。

为了证明这一点,让我们考虑一下食谱和配料之间的关系:一个 食谱 可以有许多 配料,而 配料 可以在许多 食谱 中。

多对多关系图

让我们看一下架构。

recipes
- id
- name
- ingredients
  (M2M 别名字段。 数据库中不存在,允许访问从 recipe_ingredients 链接的成分)
recipes_ingredients (交汇点集合)
- id
- recipe (存储来自 recipes.id 的外键)
- ingredient (存储来自 ingredients.id 的外键)
- quantity (“上下文”字段。 存储与关系关联的其他数据。 这些是可选的。)
ingredients
- id
- name

请注意上述架构中的以下几点。 当我们在 Directus 中创建 M2M 时:

  • 我们的联结集合,recipe_ingeredients,每行包含两个外键列。 这就是创建两个表之间关系的原因。
  • 假设 M2M 别名字段是在“recipes”集合中创建的,Directus 不会自动添加字段来显示“配料”集合中的食谱。 但是,如果需要,您可以在 ingredients 中配置别名字段:
ingredients
- id
- name
- recipes
  (数据库中不存在的 O2M 别名字段,可以访问与成分相关的所有配方)
  • 请注意,junction 集合还有一个“数量”字段,用于跟踪配方所需的每种成分的数量。 这称为_上下文字段_。 Data Studio 提供对联结集合的完全访问权限,因此您可以向联结集合添加任意数量的上下文字段。
  • 您还可以拥有连接_相同集合_中的项目的自引用 M2M 关系。 一个例子是“相关文章”,其中每篇文章都与许多其他文章相关。

配置 M2M
配置 M2M 的最简单方法是遵循有关如何 创建字段(标准) 的指南并选择 多对多 来自模板向导。

多对任意 (M2A)

有时称为 matrix fieldreplicator,M2A 关系允许您将父集合中的项目链接到数据库中任何集合中的任何项目。 当您在 Directus 中配置 M2A 时,会创建一个 M2A 别名 字段以及一个连接集合,就像我们在 M2M 关系中看到的那样。 不同之处在于,M2A 上的联结集合也有一个字段来存储相关集合的集合键 (集合的名称)

使用 M2A 的一个常见示例是 page builder,它有一个 pages 集合,该集合为每种类型的页面部分组合了多个集合,例如 headingtext_bodiesimagevideo等等 .

多对任意关系图

让我们看一下架构:

pages
- id
- name
- sections
  (数据库中不存在 M2A 别名字段。 提供对 page_sections 中项目的访问。)
page_sections (junction collection)
- id
- pages_id
  (一个 M2O,存储 pages.id 中的外键)
- collection
  (M2O,存储相关集合的名称,例如标题、text_bodies 或图像。)
- item
  (一个 M2O,存储来自 headings.id、text.id、images.id 等的外键。)
headings
- id
- title
text_bodies
- id
- text
images
- id
- file

请注意上述架构中的以下几点。 当我们在 Directus 中创建 M2A 时:

  • 与 M2O 和 M2M 关系相比,您可能需要在相关集合上配置别名字段的可能性较低,例如 headingstext_bodiesimages,因为这些集合可能没有那么有用 父集合。
  • 每个集合都有一个唯一的集合名称,因此它可以作为 page_sections.collection 字段中的足够外键。

配置 M2A
配置 M2A 的最简单方法是遵循有关如何 创建字段(标准) 的指南并选择 **Many to Any ** 模板向导的界面。

翻译 (O2M)

Directus 提供了这种专门用于处理翻译的特殊关系接口。当您在 Data Studio 中创建 Translations O2M 时,您的数据模型中会发生以下情况。将创建 Translations O2M 别名字段。创建一个联结集合和一个“语言”集合。您的所有翻译都存储在您配置的联结集合上的上下文字段中。因此,当您创建 Translations O2M 时,您也在幕后创建了 M2M 关系。所以请记住,它之所以称为 Translations O2M,是因为我们与 Translations O2M 别名字段进行交互。但在幕后,它是由 M2M 驱动的。

为了演示,让我们为“文章”创建一个翻译 O2M 关系,这是一种您可能想要翻译的常见内容类型。

翻译 O2M

让我们看一下架构。

articles
- id
- author (未翻译的字段)
- date_published (未翻译的字段)
- translations (数据表中不存在 Translations O2M 别名字段。 允许访问 article_translations 中的项目)
article_translations
- id
- article_id (一个 M2O,存储外键 article.id)
- language_id (一个M2O,存储外键language.language_code)
- title (由您创建的上下文字段。 存储文章标题的翻译)
- text (由您创建的上下文字段。 存储您创建的文章 TitleaA 上下文字段的翻译。 存储文章文本的翻译)
languages
- language_code (一个主键。 手动输入的语言代码,例如“en-US”)
- name  (存储语言名称,例如“English”)

请注意上述架构中的以下几点。当我们创建翻译 O2M 时:

  • 正如 article_translations.titlearticle_translations.text 所示,任何 translated 字段都应作为上下文字段添加到联结集合中。
  • 您不必将其用于翻译。您可以根据需要构建数据模型。您可以为每个翻译创建单独的字段,例如title_englishtitle_germantitle_chinese等。但是,这并不容易扩展,并且它创建了一种次优体验,即在项目详细信息页面上对每个字段进行每个单独的翻译。 Translations O2M 别名字段专为简化翻译过程而设计。
  • 有时您可能希望使预先存在的父字段可翻译。为此,您可以复制一个字段,将其移动到翻译集合中,然后删除父字段。但是,请注意复制字段 复制任何现有字段值。

配置翻译 O2M
配置翻译关系的最简单方法是遵循如何创建字段(标准)的指南并选择 Translations O2M 模板向导的界面。