## 變更(Mutations)
大多數關于 `GraphQL` 的討論都集中在數據獲取上,但任何完整的數據平臺也需要一種修改服務器端數據的方法。 在 REST 中,任何請求最終都可能對服務器造成副作用,但最佳實踐建議我們不應修改 `GET` 請求中的數據。 `GraphQL` 是類似的——從技術上講,任何查詢都可以實現來導致數據寫入。 但是,與 `REST` 一樣,建議遵守約定,即任何導致寫入的操作都應通過突變顯式發送([在這里閱讀更多](http://graphql.cn/learn/queries/#mutations)閱讀更多內容)。
`Apollo` 官方文檔使用 `upvotePost()` 變更示例。 這個變更實現了一種增加帖子投票屬性值的方法。 為了在 Nest 中創建等效的突變,我們將使用 `@Mutation() `裝飾器。
### **代碼優先**
讓我們使用 在上一節中AuthorResolver另一種方法(參見[解析圖](https://docs.nestjs.com/graphql/resolvers))。
```typescript
@Resolver(of => Author)
export class AuthorResolver {
constructor(
private readonly authorsService: AuthorsService,
private readonly postsService: PostsService,
) {}
@Query(returns => Author, { name: 'author' })
async getAuthor(@Args({ name: 'id', type: () => Int }) id: number) {
return await this.authorsService.findOneById(id);
}
@Mutation(returns => Post)
async upvotePost(@Args({ name: 'postId', type: () => Int }) postId: number) {
return await this.postsService.upvoteById({ id: postId });
}
@ResolveProperty('posts')
async getPosts(@Parent() author) {
const { id } = author;
return await this.postsService.findAll({ authorId: id });
}
}
```
> 所有裝飾器(例如,`@Resolver`、`@ResolveField`、`@Args` 等)都從 `@nestjs/graphql`包中導出。
`upvotePost()` 取 `postId`(`Int`)作為輸入參數,并返回更新的 `Post` 實體。出于與解析器部分相同的原因,我們必須明確設置預期類型。
如果突變需要將對象作為參數,我們可以創建一個輸入類型。 輸入類型是一種特殊的對象類型,可以作為參數傳入(在[此處](https://graphql.org/learn/schema/#input-types)閱讀更多內容)。 要聲明輸入類型,請使用 `@InputType()` 裝飾器。
```typescript
@InputType()
export class UpvotePostInput {
@Field() postId: number;
}
```
> `@InputType()` 和 `@Field()` 需要從`type-graphql` 包導入。
>`@InputType()` 裝飾器將選項對象作為參數,例如,您可以指定輸入類型的描述。 請注意,由于 `TypeScript `的元數據反射系統限制,您必須使用 `@Field` 裝飾器手動指示類型,或使用 CLI 插件。
然后我們可以在解析器類中使用這種類型:
```typescript
@Mutation(returns => Post)
async upvotePost(
@Args('upvotePostData') upvotePostData: UpvotePostInput,
) {}
```
#### ** 架構優先 **
讓我們擴展我們在上一節中AuthorResolver的用法(見[解析圖](https://docs.nestjs.com/graphql/resolvers))。
```typescript
@Resolver('Author')
export class AuthorResolver {
constructor(
private readonly authorsService: AuthorsService,
private readonly postsService: PostsService,
) {}
@Query('author')
async getAuthor(@Args('id') id: number) {
return await this.authorsService.findOneById(id);
}
@Mutation()
async upvotePost(@Args('postId') postId: number) {
return await this.postsService.upvoteById({ id: postId });
}
@ResolveProperty('posts')
async getPosts(@Parent() { id }) {
return await this.postsService.findAll({ authorId: id });
}
}
```
請注意,我們假設業務邏輯已移至 `PostsService`(分別查詢 `post` 和 incrementing `votes` 屬性)。
### 類型定義
最后一步是將我們的變更添加到現有的類型定義中。
```typescript
type Author {
id: Int!
firstName: String
lastName: String
posts: [Post]
}
type Post {
id: Int!
title: String
votes: Int
}
type Query {
author(id: Int!): Author
}
type Mutation {
upvotePost(postId: Int!): Post
}
```
該 `upvotePost(postId: Int!): Post` 變更現在可以作為我們應用程序的 GraphQL API 的一部分調用。
- 介紹
- 概述
- 第一步
- 控制器
- 提供者
- 模塊
- 中間件
- 異常過濾器
- 管道
- 守衛
- 攔截器
- 自定義裝飾器
- 基礎知識
- 自定義提供者
- 異步提供者
- 動態模塊
- 注入作用域
- 循環依賴
- 模塊參考
- 懶加載模塊
- 應用上下文
- 生命周期事件
- 跨平臺
- 測試
- 技術
- 數據庫
- 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?