4. 构建我们的架构
10
您目前所看的是本课程的较旧版本。 查看课程变更日志.

✏️让我们定义架构

在我们的 IDE 中打开最新检出的 Catstronauts 项目,让我们导航至server/src/目录。在其中,我们将创建一个新的 schema.js文件。

要开始使用我们的架构,首先我们需要几个软件包: apollo-servergraphql

  • graphql 软件包为解析和验证 查询提供了核心逻辑。
  • 的 Apollo 服务器包提供与规范兼容的 GraphQL 服务器服务器,它还提供了一些不错的实用工具,如 gql字符串模版,我们稍后将用到。

server/目录运行以下命令:

npm install apollo-server graphql

现在在 schema.js中,我们从 apollo-server中获取 gql字符串模版:

const { gql } = require("apollo-server");

我们正在导入的这个 gql是什么?它是一个标记字符串模版,用于包装 字符串,比如我们即将编写的模式定义。

这会将 字符串转换为 Apollo 库在使用 和模式时所期望的格式,同时还能启用语法高亮。

接下来,我们声明一个 typeDefs(“类型定义”的简称)常量,赋值 gql模版,我们的定义将放入其中。趁此机会,我们现在导出 typeDefs,因为我们稍后在服务器文件中会用到它。

const typeDefs = gql`
# Schema definitions go here
`;
module.exports = typeDefs;

注意使用反引号 (`) 和 gql标签,不要与单引号 (') 混淆。

太好了,我们准备定义我们的类型。参考我们的模型,我们确定我们为每条学习轨道需要以下数据

  • 标题
  • 缩略图
  • 长度
  • 模块数量
  • 作者姓名
  • 作者图片

我们如何将这些数据整理到类型中?

好吧,我们可以创建一个名为 Track 的单一类型,将所有 都添加到其中,然后称之为一天。但从业务领域的角度来看,这样做有意义吗?不一定。对于初学者来说,单个作者可能会创建多个课程,而该作者的信息将不必要地在多个位置重复。相反,我们需要从独立实体的角度考虑问题。我们从两个开始: TrackAuthor

类型 Track

我们从类型 Track 开始,表示特定的学习课程。让我们定义类型并立即添加说明:

"A track is a group of Modules that teaches about a specific topic"
type Track {
# Fields go here
}

现在是课程的 ,我们将拥有:

  • id 类型为 ID!
  • title 类型为 String!
  • author 类型为 Author! (当我们完成 Track 后,我们将定义 Author 类型)
  • thumbnail 类型为 String (课程卡片的图像的 URL)
  • length 类型为 Int
  • modulesCount 类型为 Int

以下是我们完整的 Track 类型:

"A track is a group of Modules that teaches about a specific topic"
type Track {
id: ID!
title: String!
author: Author!
thumbnail: String
length: Int
modulesCount: Int
}

我们如何确定允许哪些 为 null?一种方法是让模式反映我们的“业务”领域规则。就我们而言,例如,一条课程可能没有缩略图,但从我们的“业务”角度来看,一条没有标题或作者的课程没有任何意义。

字段类型后跟感叹号表示什么?

为每个添加一些好的描述,然后我们继续进行Author类型。

Author 类型

"Author of a complete Track or a Module"
type Author {
# Fields go here
}

Author类型仅包含三个:

  • id 类型为 ID!
  • name类型为String!
  • photo类型为String

以下是完整类型

"Author of a complete Track or a Module"
type Author {
id: ID!
name: String!
photo: String
}

非常好,我们的第一个功能现已在我们的架构中得到充分体现。这些是我们能够检索的数据类型。

不过我们仍然缺少一部分:如何告知当我们它时应该检索什么。请记住,我们没有像 REST API 那样的多个特定端点来针对不同的类型。相反,我们定义了特殊Query类型。

Query 类型

Query类型定义类似于任何其他:

type Query {
# Fields go here
}

该类型的字段是进入我们架构其他部分的入口点。这些是我们的客户端可以查询的顶级字段

现在,我们只针对主页获取曲目列表感兴趣。我们将具体 tracksForHome命名得尽可能具有描述性。我们要让此 返回一个非空 Track列表。我们还会添加一个好的说明:

type Query {
"Get tracks array for homepage grid"
tracksForHome: [Track!]!
}

现在,我们的架构已完全明确,足以支持我们的首要功能!以下是整个架构的外观

type Query {
"Get tracks array for homepage grid"
tracksForHome: [Track!]!
}
"A track is a group of Modules that teaches about a specific topic"
type Track {
id: ID!
"The track's title"
title: String!
"The track's main author"
author: Author!
"The track's main illustration to display in track card or track page detail"
thumbnail: String
"The track's approximate length to complete, in minutes"
length: Int
"The number of modules this track contains"
modulesCount: Int
}
"Author of a complete Track"
type Author {
id: ID!
"Author's first and last name"
name: String!
"Author's profile picture url"
photo: String
}
下面哪些始终是关于 Query 类型的始终正确的?

现在我们的基础架构已准备就绪,我们可以开始工作于

代码挑战!

创建包含以下内容的完整架构:类型 Query,其中包含一个字段 spaceCats,用于获取 ListSpaceCat。类型 SpaceCat,及其子字段:类型为 ID!id、类型为 String!name、类型为 Intage,以及类型为 ListMissionmissions。最后定义 Mission 类型及其子字段:类型为 ID!id、类型为 String!name,以及类型为 String!description

上一个

分享你关于此课程的问题和评论

您的反馈有助于我们改进网站!如果您遇到了障碍或困惑,欢迎您告知我们,我们会为您提供帮助。所有评论都是公开的,并且必须遵守 Apollo 行为准则。请注意,已经解决或处理的评论可能会被删除。

您需要一个 GitHub 帐户才能在此处发布。没有帐户? 改为在我们的 Odyssey 论坛中发帖。