GraphQL查询可以遍历相关对象及其字段,因此只需使用一个查询即可编写如下所示的内容:
{
books
{
items {
id
title
authors {
items {
first_name
last_name
}
}
}
}
}
检索书籍及其作者。
若要允许此功能正常工作,数据 API 生成器需要知道这两个对象是如何相互关联的。
relationships
配置文件中的 节提供了使此功能正确且高效地工作所需的元数据。
配置关系
无论使用哪个数据库与数据 API 生成器一起使用,必须显式告知数据 API 生成器,一个对象与另一个对象相关。 在两个实体之间可以建立三种类型的关系:
一对多关系
一对多关系允许对象访问相关对象的列表。 例如,书籍系列可以允许访问该系列中的所有书籍:
{
series {
items {
name
books {
items {
title
}
}
}
}
}
如果有外键支持两个基础数据库对象之间的关系,则只需告诉数据 API 生成器,你希望公开这种关系。 使用 DAB CLI:
dab update Series --relationship books --target.entity Book --cardinality many
series
更新实体 - 在示例中使用:
"Series": {
"source": "dbo.series",
...
"relationships": {
"books": {
"target.entity": "Book",
"cardinality": "many"
}
}
...
}
新键在 元素下 relationships
添加: books
。 元素定义用于GraphQL字段的名称,以便从 series
对象导航到 在 中target.entity
Book
定义的 对象。 这意味着配置文件中必须存在名为 的 Book
实体。
属性cardinality
告知数据 API 生成器,每个系列中可以有许多书籍,因此创建的GraphQL字段返回项列表。
该属性就是你所需要的。 启动时,数据 API 生成器会自动检测需要用于维持已定义关系的数据库字段。
如果没有外键约束来维持数据库关系,数据 API 生成器无法自动找出使用了哪些字段。 若要告知数据 API 生成器哪些字段与这两个实体相关,必须手动指定它们。 可以使用 CLI dab update
指定它们:
dab update Series --relationship books --target.entity Book --cardinality many --relationship.fields "id:series_id"
使用 选项 relationship.fields
可以定义 () Series
更新的实体使用哪些字段,以及从目标实体 (Book
) 使用哪些字段,以将数据从一个实体连接到另一个实体。
在前面的示例中,id
实体的数据库字段Series
与实体的数据库字段series_id
Book
匹配。
配置还包含以下信息:
"Series": {
"source": "dbo.series",
...
"relationships": {
"books": {
"cardinality": "many",
"target.entity": "Book",
"source.fields": ["id"],
"target.fields": ["series_id"]
}
}
...
}
多对一关系
多对一关系类似于一对多关系,有两个主要区别:
- 设置为
cardinality
one
- 创建的 GraphQL 字段返回标量而不是列表
按照之前使用的书籍系列示例,一本书只能位于一个系列中,因此使用以下 DAB CLI 命令创建关系:
dab update Book --relationship series --target.entity Series --cardinality one
生成此配置:
"Book": {
"source": "dbo.books",
...
"relationships": {
"series": {
"target.entity": "Series",
"cardinality": "one"
}
}
}
这反过来又允许GraphQL查询,如下例所示:
{
books {
items {
id
title
series {
name
}
}
}
}
每本书还返回其所属的系列。
多对多关系
多对多关系可视为一对多关系和多对一关系协同工作。 一个作者当然可以写多本书 (一对多关系) ,但同样事实是,多个作者可以 (多对一关系) 处理同一本书。
数据 API 生成器本机支持这种类型的关系:
- 使用一对多/多对一关系。
- 使用 链接对象。
使用一对多/多对一关系
一个业务要求,可能是跟踪版税是如何在书籍作者之间分配的。 若要实现此类要求,需要一个将作者、书籍和分配的版税链接在一起的专用实体。 因此,需要三个实体:
-
authors
,表示作者的简历详细信息。 -
books
,表示书籍数据,如标题和国际标准书号 (ISBN) 。 -
books_authors
表示与书籍及其作者相关的数据,例如,作者为特定书籍获得的版税百分比。
可以通过下图可视化这三个实体。
可见,有两个双向关系:
- 与 之间的
authors
一对多/多对一关系books_authors
- 与 之间的
books
一对多/多对一关系books_authors
若要正常使用 DAB 处理此类方案,只需在配置文件中创建相关实体和映射即可。 假设 Book
和 Author
实体已在配置文件中:
dab add BookAuthor --source dbo.books_authors --permissions "anonymous:*"
若要添加新实体,请运行 dab update
:
dab update Book --relationship authors --target.entity BookAuthor --cardinality many --relationship.fields "id:book_id"
dab update Author --relationship books --target.entity BookAuthor --cardinality many --relationship.fields "id:author_id"
若要将关系添加到新创建的 BookAuthor
实体,请再次运行 dab update
:
dab update BookAuthor --relationship book --target.entity Book --cardinality one --relationship.fields "book_id:id"
dab update BookAuthor --relationship author --target.entity Author --cardinality one --relationship.fields "author_id:id"
将 关系从 BookAuthor
Book
添加到 和 Author
实体。 使用提供的配置,DAB 能够处理嵌套查询,如以下示例所示:
{
authors {
items {
first_name
last_name
books {
items {
book {
id
title
}
royalties_percentage
}
}
}
}
}
当你要求归还所有作者的地方,他们写的书以及相关的版税。
使用链接对象
如果需要通过GraphQL访问多对多关系中涉及的所有实体,则上一部分所述的过程非常有效。 这种情况并非总是如此。 例如,如果不需要跟踪版税,实体 BookAuthor
不会真正为最终用户带来任何价值。 该实体仅用于将书籍与其作者相关联。 在关系数据库中,多对多关系是使用这样的第三个表创建的,该表将参与多对多关系的表 链接 在一起:
在关系图中,可以看到有一个名为 books_authors
的表,该表将作者与其书籍和书籍与其作者链接在一起。 此链接表不需要向最终用户公开。 链接表只是允许多对多关系存在的项目,但数据 API 生成器需要知道其存在才能正确使用它。
DAB CLI 可用于创建多对多关系,并配置链接对象 (确保删除在上一部分中创建的所有关系,并且仅从 Book
和 Author
实体开始,并且它们之间已) 没有配置的关系:
dab update Book --relationship authors --target.entity Author --cardinality many --relationship.fields "id:id" --linking.object "dbo.books_authors" --linking.source.fields "book_id" --linking.target.fields "author_id"
它更新 JSON 配置文件,如下所示:
"Book": {
"source": "dbo.books",
...
"relationships": {
"authors": {
"cardinality": "many",
"target.entity": "author",
"source.fields": [ "id" ],
"target.fields": [ "id" ],
"linking.object": "dbo.books_authors",
"linking.source.fields": [ "book_id" ],
"linking.target.fields": [ "author_id" ]
}
}
}
该配置告知 DAB 你要在Book
实体中添加一个authors
允许访问书籍作者的字段。
authors
可以是 many
,因此当GraphQL查询访问authors
字段时,将返回作者列表。 此关系定义如何 从 书籍 导航到 作者:用于从书籍导航到作者的数据库字段在 书籍的 中 source.fields
定义,在 作者的 中 target.fields
定义,类似于本文前面所述的一对多或多对一关系。
此关系是多对多关系,因此两个实体之间没有直接连接,因此 linking.object
需要使用 。 在示例中,数据库表 dbo.books_authors
用作链接对象。 链接对象如何能够将书籍连接到其作者在 和 linking.target.fields
属性中linking.source.fields
定义。 第一个命令告诉 DAB 源实体 ( - - Book
如何连接到喜欢对象),第二个告知链接对象如何连接到示例中的目标实体 Author
。
若要了解如何使用提供的信息,可以使用以下示例等效查询:
select *
from dbo.books as b
inner join dbo.books_authors as ba on b.id = ba.book_id
inner join dbo.authors a on ba.author_id = a.id
使用提供的配置,DAB 能够理解GraphQL,如以下示例所示:
{
books {
items {
id
title
authors {
items {
first_name
last_name
}
}
}
}
}
你想在哪里获取书籍及其作者。
若要允许从 Author
导航到 Book
,可以应用相同的原则,使用以下命令更新配置:
dab update Author --relationship books --target.entity Book --cardinality many --relationship.fields "id:id" --linking.object "dbo.books_authors" --linking.source.fields "author_id" --linking.target.fields "book_id"
它定义实体与实体之间的Author
多对多关系,在后台使用链接对象dbo.books_authors
。Book