## 复杂性
> 此章节仅适应于代码优先模式。
查询复杂性允许你定义某些字段的复杂程度,并限制**最大复杂性**的查询。其原理是通过使用一个简单的数字来定义每个字段的复杂度。通常每个字段的复杂度默认为1。另外,GraphQL 查询的复杂性计算可以使用所谓的复杂度估算器进行定制。复杂度估算器是一个计算字段复杂度的简单函数。你可以将任意数量的复杂度估算器添加到规则中,然后一个接一个地执行。第一个返回数字复杂度值的估算器确定该字段的复杂度。
`@nestjs/graphql` 包与 <span style="color:red">graphql-query-complexity</span> 等工具能很好地集成,他们提供了一种基于成本分析的解决方案。有了这个库,你可以拒绝在你的 GraphQL 服务中执行成本过高的查询。
### 安装
要开始使用它,我们首先要安装它所需要的依赖包。
```bash
$npm install --save graphql-query-complexity
```
### 快速开始
一旦安装完,我们就可以定义 `ComplexityPlugin` 这个类:
```typescript
import { GraphQLSchemaHost, Plugin } from '@nestjs/graphql';
import {
ApolloServerPlugin,
GraphQLRequestListener,
} from 'apollo-server-plugin-base';
import { GraphQLError } from 'graphql';
import {
fieldExtensionsEstimator,
getComplexity,
simpleEstimator,
} from 'graphql-query-complexity';
@Plugin()
export class ComplexityPlugin implements ApolloServerPlugin {
constructor(private gqlSchemaHost: GraphQLSchemaHost) {}
requestDidStart(): GraphQLRequestListener {
const { schema } = this.gqlSchemaHost;
return {
didResolveOperation({ request, document }) {
const complexity = getComplexity({
schema,
operationName: request.operationName,
query: document,
variables: request.variables,
estimators: [
fieldExtensionsEstimator(),
simpleEstimator({ defaultComplexity: 1 }),
],
});
if (complexity >= 20) {
throw new GraphQLError(
`Query is too complex: ${complexity}. Maximum allowed complexity: 20`,
);
}
console.log('Query Complexity:', complexity);
},
};
}
}
```
为了演示,我们将允许的最大复杂度指定为 20。在上面的示例中,我们使用了 2 个估算器,`simpleEstimator` 和 `fieldExtensionsEstimator`。
- `simpleEstimator`:该简单估算器为每个字段返回一个固定复杂度
- `fieldExtensionsEstimator`:字段扩展估算器提取 schema 中每个字段的复杂度值
> 别忘了将此类添加到任意模块的提供者数组中。
### 字段级复杂性
有了这个插件,我们可以为任意字段定义复杂度了,做法就是在传递给 `@Field()` 装饰器的选项对象中,指定 `complexity` 属性的值,如下所示:
```typescript
@Field({ complexity: 3 })
title: string;
```
或者,你也可以定义估算器函数:
```typescript
@Field({ complexity: (options: ComplexityEstimatorArgs) => ... })
title: string;
```
### 查询/变更级复杂性
此外,`@Query` 和 `@Mutation()` 装饰器也具有复杂性属性,可以被这样指定:
```typescript
@Query({ complexity: (options: ComplexityEstimatorArgs) => options.args.count * options.childComplexity })
items(@Args('count') count: number) {
return this.itemsService.getItems({ count });
}
```
- 介绍
- 概述
- 第一步
- 控制器
- 提供者
- 模块
- 中间件
- 异常过滤器
- 管道
- 守卫
- 拦截器
- 自定义装饰器
- 基础知识
- 自定义提供者
- 异步提供者
- 动态模块
- 注入作用域
- 循环依赖
- 模块参考
- 懒加载模块
- 应用上下文
- 生命周期事件
- 跨平台
- 测试
- 技术
- 数据库
- Mongo
- 配置
- 验证
- 缓存
- 序列化
- 版本控制
- 定时任务
- 队列
- 日志
- Cookies
- 事件
- 压缩
- 文件上传
- 流式处理文件
- HTTP模块
- Session(会话)
- MVC
- 性能(Fastify)
- 服务器端事件发送
- 安全
- 认证(Authentication)
- 授权(Authorization)
- 加密和散列
- Helmet
- CORS(跨域请求)
- CSRF保护
- 限速
- GraphQL
- 快速开始
- 解析器(resolvers)
- 变更(Mutations)
- 订阅(Subscriptions)
- 标量(Scalars)
- 指令(directives)
- 接口(Interfaces)
- 联合类型
- 枚举(Enums)
- 字段中间件
- 映射类型
- 插件
- 复杂性
- 扩展
- CLI插件
- 生成SDL
- 其他功能
- 联合服务
- 迁移指南
- Websocket
- 网关
- 异常过滤器
- 管道
- 守卫
- 拦截器
- 适配器
- 微服务
- 概述
- Redis
- MQTT
- NATS
- RabbitMQ
- Kafka
- gRPC
- 自定义传输器
- 异常过滤器
- 管道
- 守卫
- 拦截器
- 独立应用
- Cli
- 概述
- 工作空间
- 库
- 用法
- 脚本
- Openapi
- 介绍
- 类型和参数
- 操作
- 安全
- 映射类型
- 装饰器
- CLI插件
- 其他特性
- 迁移指南
- 秘籍
- CRUD 生成器
- 热重载
- MikroORM
- TypeORM
- Mongoose
- 序列化
- 路由模块
- Swagger
- 健康检查
- CQRS
- 文档
- Prisma
- 静态服务
- Nest Commander
- 问答
- Serverless
- HTTP 适配器
- 全局路由前缀
- 混合应用
- HTTPS 和多服务器
- 请求生命周期
- 常见错误
- 实例
- 迁移指南
- 发现
- 谁在使用Nest?