梗概
- graphQL类似数据库查询语言,可以按需获取对应资源
- 也是需要服务端的文档
- 虽然graphQL提供了schema供客户端查看服务端开放的所有接口,但返回的内容非常多,且相对扁平化,没有很强的结构性,难以查找所需的接口
- 如GitHub的就返回了15万行的json
- 虽然graphQL提供了schema供客户端查看服务端开放的所有接口,但返回的内容非常多,且相对扁平化,没有很强的结构性,难以查找所需的接口
100s视频了解
【熟肉】100 秒了解 GraphQL_哔哩哔哩_bilibili
官方描述
官方已经描述的非常简洁清楚:GraphQL | A query language for your API
使用教程
API传输载体
HTTP
- 可以选择使用http来发送graphQL
- 在body中放入graphQL

- 在body中放入graphQL
客户端
示例
child::
vue中使用apollo访问graphQL接口
指向原始笔记的链接
配置 Apollo 客户端: 创建一个
apollo.js文件来配置 Apollo 客户端:// src/apollo.js import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client/core'; import { DefaultApolloClient } from '@vue/apollo-composable'; import { provide } from 'vue'; const httpLink = createHttpLink({ uri: 'https://your-graphql-endpoint.com/graphql', }); const cache = new InMemoryCache(); const apolloClient = new ApolloClient({ link: httpLink, cache, }); export function provideApolloClient(app) { app.provide(DefaultApolloClient, apolloClient); }在 Vue 应用中提供 Apollo 客户端: 在
main.js中引入并提供 Apollo 客户端:// src/main.js import { createApp } from 'vue'; import App from './App.vue'; import { provideApolloClient } from './apollo'; const app = createApp(App); provideApolloClient(app); app.mount('#app');使用 Apollo 查询数据: 在组件中使用
useQuery来执行 GraphQL 查询:<!-- src/components/HelloWorld.vue --> <template> <div> <h1>GraphQL Query Example</h1> <div v-if="loading">Loading...</div> <div v-if="error">Error: {{ error.message }}</div> <div v-if="data"> <p>{{ data.hello }}</p> </div> </div> </template> <script> import { useQuery } from '@vue/apollo-composable'; import gql from 'graphql-tag'; const HELLO_QUERY = gql` query Hello($name: String!) { hello(name: $name) } `; export default { setup() { const { result: data, loading, error } = useQuery(HELLO_QUERY, { name: 'World' }); return { data, loading, error }; }, }; </script>
graphQL语句
child::
graphQL语句
图解
- Introduction to GraphQL | GraphQL官网的示例就非常简单易懂且典型
操作
- 一个基本单位
- 一个操作有多种类型:查、增改、subscription
- 这是用来显性告诉服务器这个操作的目的
- 实际上的增删改查还得取决于服务器怎么解析这个请求
- 一个操对应一个大括号,大括号里面填写请求内容
操作名
- 放在操作的大括号前面
- 可以忽略,即匿名操作
示例
增删改查
child::graphQL增删改查
指向原始笔记的链接
接口内容探索
child::
接口内容探索
梗概
- 服务端懂的graphQL一般内置一个graphQL playground,用以方便探索schema,并借助返回的内嵌文档探索
示例
查看字段:
child::
选择所需字段:
指向原始笔记的链接
注释
- 请求中可以用
#来插入一行注释
字段参数
示例
{
human(id: "1000") {
name
height
}
}- 请求human列表中包含id:“1000”这一个键值对的元素
变量
- 可以给操作定义一个变量(参数)
- 在操作中就可以使用这个变量
- 还可以给这个变量定义一个默认值
- 变量可以在操作外赋值
示例

别名
- 可以给某个请求字段起一个别名,让结构返回这个别名,而不是原字段名
片段
- 可以在请求外定义一个片段,其实就是一些请求的集合
- 在别的请求中,可以调用这个片段,就相当于在调用的地方写下了片段中的请求
变量
- 片段可以使用调用方请求的变量
指令
- 在某些请求字段后,可以追加一个指令
- 指令可以使用操作中的变量
- 指令会对字段进行一定的修改
字段 @include()会根据表达式内的真假来判断是否发送该字段请求- 即最终结果是否包含该字段
示例
@include(if: Boolean) 指令允许你根据条件包含某个字段。
query getUser($showEmail: Boolean!) {
user(id: "1") {
id
name
email @include(if: $showEmail)
}
}在这个示例中,如果变量 showEmail 为 true,则会返回用户的电子邮件;如果为 false,则不会返回电子邮件字段。
缓存
child::
graphQL客户端缓存
方案
指向原始笔记的链接
- child::Apollo Client Cache
- Relay Cache:Relay 是 Facebook 开发的 GraphQL 客户端,也内置了缓存系统。Relay 根据查询的 Fragment 结构来缓存数据,并确保缓存与查询结果保持同步。
服务端
服务端定义字段
child::
定义graphQL
示例
NestJs
配置 GraphQL 模块: 在你的主模块(例如
app.module.ts)中导入并配置GraphQLModule:import { Module } from '@nestjs/common'; import { GraphQLModule } from '@nestjs/graphql'; import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo'; import { join } from 'path'; @Module({ imports: [ GraphQLModule.forRoot<ApolloDriverConfig>({ driver: ApolloDriver, autoSchemaFile: join(process.cwd(), 'src/schema.gql'), }), ], }) export class AppModule {}定义 GraphQL 类型: 创建用户(User)和帖子(Post)类型,并定义它们之间的关系。 TypeScript
import { ObjectType, Field, Int, ID } from '@nestjs/graphql'; @ObjectType() export class User { @Field(type => ID) id: number; @Field() name: string; @Field(type => [Post]) posts: Post[]; } @ObjectType() export class Post { @Field(type => ID) id: number; @Field() title: string; @Field() content: string; @Field(type => User) author: User; }创建 Resolver: 创建用户和帖子解析器,处理查询和变更。
import { Resolver, Query, Mutation, Args, ResolveField, Parent } from '@nestjs/graphql'; import { User } from './user.model'; import { Post } from './post.model'; @Resolver(of => User) export class UserResolver { @Query(returns => [User]) users(): User[] { // 返回用户列表 } @ResolveField(returns => [Post]) posts(@Parent() user: User): Post[] { // 根据父字段user的请求相应值返回用户的帖子列表 } } @Resolver(of => Post) export class PostResolver { @Query(returns => [Post]) posts(): Post[] { // 返回帖子列表 } @Mutation(returns => Post) createPost(@Args('title') title: string, @Args('content') content: string, @Args('authorId') authorId: number): Post { // 创建并返回新帖子 } @ResolveField(returns => User) author(@Parent() post: Post): User { // 根据父字段的值来返回帖子的作者 } }指向原始笔记的链接
- 对于关联类型,非常适合使用dataloader来解决n+1问题
开启graphQL playground
child::
graphQL playground
梗概
- 相当于一个graphQL接口的交互式文档
开启playground
示例(NestJs)
@Module({ imports: [ GraphQLModule.forRoot<ApolloDriverConfig>({ driver: ApolloDriver, playground: true, }), ], })使用
child::
指向原始笔记的链接接口内容探索
梗概
- 服务端懂的graphQL一般内置一个graphQL playground,用以方便探索schema,并借助返回的内嵌文档探索
示例
查看字段:
child::
选择所需字段:
指向原始笔记的链接
关联数据的查询
- 使用dataloader解决n+1问题
文档
- child::
内嵌文档
- 内嵌文档的结构一般都是按照服务端定义的字段结构
- 每个字段都附有一个文档,没有字段,就没有文档
- 示例:一个字段对应一个解释
- 所以不会像笔记一样为了方便理解、归类,而把接口分类
- 所以嵌入文档都是直接对接实际业务的
- 每个字段都附有一个文档,没有字段,就没有文档
使用教程
- 结合文档的IDE,根据文档做语句补全提示,可以一边写调用语句、一边查文档
https://graphql.org/learn/introspection/ - 并不是真的图形化
实例
github graphAPI
- https://docs.github.com/en/graphql/overview/explorer 左边的文档就是根据所有字段的description字段生成的内嵌文档
- 内嵌文档的结构一般都是按照服务端定义的字段结构
- child::
graphQL schema与嵌入文档的关系
示例
github
- 嵌入文档也是从服务端同一个端点中使用graphQL请求获取的
- 按照一定结构规则用指定字段存储type的数据 - schema中包含了嵌入文档的相关字段
- 通常是某个类型的描述、参数、等信息
- 嵌入文档也是从服务端同一个端点中使用graphQL请求获取的
关联数据的查询
- 使用dataloader解决n+1问题
适用范围
优点
- 可以减少网络请求次数,提高性能。
- 可以让客户端精确地获取所需的数据,没有任何冗余。
- 可以让 API 更易于演化,并启用强大的开发人员工具。
- 无需打破原有的结构
- 可以让客户端指定其需要的数据形状和粒度,从而减少了不必要的数据传输,提高了性能。
- 提供了一个图形化的IDE,非常快速方便的编写接口请求代码
- 单一端口,即单一请求链接
- 如github的:https://api.github.com/graphql
缺点
- 学习成本较高。
- 对于简单的 API,GraphQL 可能会增加复杂性。
- 需要多创建和修改一个schema
- 性能问题
- 对于需要大量计算的查询,GraphQL 可能会导致性能问题。
- 资源增加需要更多的内存
- 权限需要细化到字段
- 缓存机制复杂
示例
GitHub 的graphQL
https://docs.github.com/en/graphql
- 文档不是很详细、可读性不强
- 不如RESTful API的文档细致
- 建议先看RESTful API的文档,了解业务流程,再使用graphQL


