GraphQL 变更操作 #
变更基础 #
Mutation 是 GraphQL 中用于修改数据的操作类型,类似于 REST API 中的 POST、PUT、DELETE 请求。
text
┌─────────────────────────────────────────────────────────────┐
│ Mutation 操作特点 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ✅ 写入操作:修改服务器数据 │
│ ✅ 顺序执行:多个变更按顺序执行 │
│ ✅ 返回数据:可返回修改后的数据 │
│ ✅ 原子操作:支持事务性变更 │
│ │
└─────────────────────────────────────────────────────────────┘
Query vs Mutation #
text
┌─────────────────────────────────────────────────────────────┐
│ Query 与 Mutation 对比 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Query: │
│ - 只读操作 │
│ - 并行执行 │
│ - 可缓存 │
│ - 幂等性 │
│ │
│ Mutation: │
│ - 写入操作 │
│ - 顺序执行 │
│ - 不应缓存 │
│ - 可能非幂等 │
│ │
└─────────────────────────────────────────────────────────────┘
创建操作 #
基本创建 #
graphql
mutation {
createUser(name: "Alice", email: "alice@example.com") {
id
name
email
createdAt
}
}
响应:
json
{
"data": {
"createUser": {
"id": "1",
"name": "Alice",
"email": "alice@example.com",
"createdAt": "2024-01-15T10:30:00Z"
}
}
}
使用输入对象 #
复杂的数据结构使用输入对象更清晰:
graphql
mutation {
createUser(input: {
name: "Alice"
email: "alice@example.com"
age: 25
role: "user"
preferences: {
theme: "dark"
language: "zh-CN"
}
}) {
id
name
email
age
role
preferences {
theme
language
}
}
}
使用变量 #
graphql
mutation CreateUser($input: CreateUserInput!) {
createUser(input: $input) {
id
name
email
}
}
变量:
json
{
"input": {
"name": "Alice",
"email": "alice@example.com",
"age": 25
}
}
批量创建 #
graphql
mutation {
createUsers(inputs: [
{ name: "Alice", email: "alice@example.com" },
{ name: "Bob", email: "bob@example.com" },
{ name: "Charlie", email: "charlie@example.com" }
]) {
id
name
email
}
}
更新操作 #
基本更新 #
graphql
mutation {
updateUser(id: "1", name: "New Name") {
id
name
updatedAt
}
}
使用输入对象 #
graphql
mutation UpdateUser($id: ID!, $input: UpdateUserInput!) {
updateUser(id: $id, input: $input) {
id
name
email
age
updatedAt
}
}
变量:
json
{
"id": "1",
"input": {
"name": "New Name",
"age": 26
}
}
部分更新 #
只更新提供的字段:
graphql
mutation {
updateUser(id: "1", input: { name: "Updated Name" }) {
id
name
email
age
}
}
条件更新 #
graphql
mutation {
updateUser(
id: "1"
input: { status: "inactive" }
expectedVersion: 5
) {
id
status
version
}
}
批量更新 #
graphql
mutation {
updateUsers(
filter: { status: { eq: "pending" } }
input: { status: "active" }
) {
affectedCount
users {
id
status
}
}
}
删除操作 #
基本删除 #
graphql
mutation {
deleteUser(id: "1") {
id
success
message
}
}
软删除 #
graphql
mutation {
softDeleteUser(id: "1") {
id
deletedAt
status
}
}
批量删除 #
graphql
mutation {
deleteUsers(filter: { status: { eq: "inactive" } }) {
affectedCount
deletedIds
}
}
级联删除 #
graphql
mutation {
deleteUser(id: "1", cascade: true) {
id
deletedPosts {
id
title
}
deletedComments {
id
}
}
}
输入类型设计 #
创建输入类型 #
graphql
input CreateUserInput {
name: String!
email: String!
age: Int
role: UserRole = USER
preferences: PreferencesInput
}
input PreferencesInput {
theme: String = "light"
language: String = "en"
notifications: Boolean = true
}
使用:
graphql
mutation {
createUser(input: {
name: "Alice"
email: "alice@example.com"
preferences: {
theme: "dark"
language: "zh-CN"
}
}) {
id
name
}
}
更新输入类型 #
graphql
input UpdateUserInput {
name: String
email: String
age: Int
role: UserRole
status: UserStatus
preferences: PreferencesInput
}
嵌套输入类型 #
graphql
input CreatePostInput {
title: String!
content: String!
excerpt: String
status: PostStatus = DRAFT
tags: [String!]
category: CategoryInput
seo: SEOInput
}
input CategoryInput {
id: ID
name: String
slug: String
}
input SEOInput {
title: String
description: String
keywords: [String!]
}
输入类型最佳实践 #
text
┌─────────────────────────────────────────────────────────────┐
│ 输入类型设计原则 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 分离创建和更新输入 │
│ - CreateInput:必填字段多 │
│ - UpdateInput:所有字段可选 │
│ │
│ 2. 使用嵌套输入对象 │
│ - 组织复杂数据结构 │
│ - 提高可读性 │
│ │
│ 3. 提供默认值 │
│ - 常用字段设置默认值 │
│ - 减少客户端负担 │
│ │
│ 4. 命名规范 │
│ - 输入类型以 Input 结尾 │
│ - 操作以动词开头 │
│ │
└─────────────────────────────────────────────────────────────┘
返回类型设计 #
返回创建的对象 #
graphql
mutation {
createUser(input: { name: "Alice", email: "alice@example.com" }) {
id
name
email
createdAt
}
}
返回负载类型 #
graphql
type UserMutationPayload {
user: User
success: Boolean!
message: String
errors: [Error!]
}
type Error {
field: String!
message: String!
code: String
}
使用:
graphql
mutation {
createUser(input: { name: "Alice", email: "alice@example.com" }) {
user {
id
name
email
}
success
message
errors {
field
message
code
}
}
}
返回关联数据 #
graphql
mutation {
createPost(input: { title: "Hello", content: "World" }) {
post {
id
title
content
author {
id
name
}
comments {
id
content
}
}
}
}
错误处理 #
错误响应格式 #
json
{
"data": {
"createUser": null
},
"errors": [
{
"message": "Email already exists",
"locations": [{ "line": 2, "column": 3 }],
"path": ["createUser"],
"extensions": {
"code": "DUPLICATE_EMAIL",
"field": "email"
}
}
]
}
业务错误处理 #
graphql
mutation {
createUser(input: { name: "Alice", email: "invalid-email" }) {
user {
id
name
}
success
errors {
field
message
code
}
}
}
响应:
json
{
"data": {
"createUser": {
"user": null,
"success": false,
"errors": [
{
"field": "email",
"message": "Invalid email format",
"code": "VALIDATION_ERROR"
}
]
}
}
}
错误类型定义 #
graphql
type MutationResponse {
success: Boolean!
message: String
errors: [FieldError!]
}
type FieldError {
field: String!
message: String!
code: ErrorCode
}
enum ErrorCode {
VALIDATION_ERROR
NOT_FOUND
UNAUTHORIZED
FORBIDDEN
CONFLICT
INTERNAL_ERROR
}
多个变更 #
顺序执行 #
GraphQL 保证多个变更按顺序执行:
graphql
mutation {
createPost(input: { title: "Post 1" }) {
id
title
}
createPost(input: { title: "Post 2" }) {
id
title
}
createPost(input: { title: "Post 3" }) {
id
title
}
}
使用别名 #
graphql
mutation {
firstPost: createPost(input: { title: "First" }) {
id
title
}
secondPost: createPost(input: { title: "Second" }) {
id
title
}
}
关联变更 #
graphql
mutation {
createUser(input: { name: "Alice", email: "alice@example.com" }) {
id
name
}
createPost(input: { title: "First Post", authorId: "1" }) {
id
title
author {
name
}
}
}
事务处理 #
原子操作 #
graphql
mutation TransferMoney($from: ID!, $to: ID!, $amount: Float!) {
transferMoney(from: $from, to: $to, amount: $amount) {
success
fromAccount {
id
balance
}
toAccount {
id
balance
}
transaction {
id
amount
createdAt
}
}
}
批量事务 #
graphql
mutation BatchUpdate($operations: [BatchOperation!]!) {
batchUpdate(operations: $operations) {
success
results {
operation
success
data {
... on User {
id
name
}
... on Post {
id
title
}
}
error {
message
code
}
}
}
}
文件上传 #
单文件上传 #
graphql
mutation UploadFile($file: Upload!) {
uploadFile(file: $file) {
id
filename
mimetype
size
url
}
}
多文件上传 #
graphql
mutation UploadFiles($files: [Upload!]!) {
uploadFiles(files: $files) {
id
filename
url
}
}
带数据的文件上传 #
graphql
mutation CreatePostWithImage($input: CreatePostInput!, $image: Upload!) {
createPostWithImage(input: $input, image: $image) {
id
title
content
coverImage {
id
url
width
height
}
}
}
变更最佳实践 #
1. 命名规范 #
graphql
type Mutation {
createUser(input: CreateUserInput!): User!
updateUser(id: ID!, input: UpdateUserInput!): User!
deleteUser(id: ID!): DeleteResult!
createPost(input: CreatePostInput!): Post!
updatePost(id: ID!, input: UpdatePostInput!): Post!
deletePost(id: ID!): DeleteResult!
}
2. 使用输入类型 #
graphql
mutation CreateUser($input: CreateUserInput!) {
createUser(input: $input) {
id
name
}
}
3. 返回有意义的数据 #
graphql
mutation {
createPost(input: { title: "Hello" }) {
id
title
slug
author {
id
name
}
createdAt
}
}
4. 提供操作结果 #
graphql
mutation {
deletePost(id: "1") {
success
message
deletedId
}
}
5. 支持乐观更新 #
graphql
mutation UpdateUser($id: ID!, $input: UpdateUserInput!) {
updateUser(id: $id, input: $input) {
id
name
email
__typename
}
}
实战示例 #
示例一:用户注册 #
graphql
mutation Register($input: RegisterInput!) {
register(input: $input) {
user {
id
name
email
avatar
createdAt
}
token
success
errors {
field
message
code
}
}
}
变量:
json
{
"input": {
"name": "Alice",
"email": "alice@example.com",
"password": "securePassword123",
"confirmPassword": "securePassword123"
}
}
示例二:创建文章 #
graphql
mutation CreatePost($input: CreatePostInput!) {
createPost(input: $input) {
id
title
slug
content
excerpt
status
coverImage {
id
url
}
author {
id
name
}
tags
categories {
id
name
slug
}
seo {
title
description
keywords
}
createdAt
publishedAt
}
}
变量:
json
{
"input": {
"title": "GraphQL 入门教程",
"content": "这是一篇关于 GraphQL 的入门教程...",
"excerpt": "学习 GraphQL 的基础知识",
"status": "PUBLISHED",
"tags": ["GraphQL", "API", "Tutorial"],
"categoryIds": ["1", "2"],
"seo": {
"title": "GraphQL 入门教程 - 完整指南",
"description": "从零开始学习 GraphQL",
"keywords": ["GraphQL", "API"]
}
}
}
示例三:更新用户资料 #
graphql
mutation UpdateProfile($input: UpdateProfileInput!) {
updateProfile(input: $input) {
id
name
email
avatar
bio
location
website
socialLinks {
twitter
github
linkedin
}
preferences {
theme
language
notifications
}
updatedAt
}
}
示例四:批量操作 #
graphql
mutation BatchOperation($operations: [BatchOperationInput!]!) {
batchOperation(operations: $operations) {
success
results {
id
operation
success
data {
... on User {
id
name
status
}
... on Post {
id
title
status
}
}
error {
message
code
}
}
summary {
total
successful
failed
}
}
}
变量:
json
{
"operations": [
{
"type": "UPDATE_USER",
"id": "1",
"data": { "status": "active" }
},
{
"type": "UPDATE_USER",
"id": "2",
"data": { "status": "active" }
},
{
"type": "DELETE_POST",
"id": "100"
}
]
}
示例五:评论系统 #
graphql
mutation CreateComment($input: CreateCommentInput!) {
createComment(input: $input) {
id
content
status
author {
id
name
avatar
}
post {
id
title
commentCount
}
parent {
id
content
}
replies {
id
content
}
createdAt
}
}
安全考虑 #
输入验证 #
graphql
input CreateUserInput {
name: String! @constraint(minLength: 2, maxLength: 50)
email: String! @constraint(format: "email")
age: Int @constraint(min: 0, max: 150)
password: String! @constraint(minLength: 8, pattern: "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]+$")
}
权限控制 #
graphql
mutation {
deleteUser(id: "1") {
id
success
}
}
服务端验证:
javascript
const resolvers = {
Mutation: {
deleteUser: async (_, { id }, context) => {
if (!context.user) {
throw new AuthenticationError('Not authenticated');
}
if (context.user.role !== 'admin') {
throw new ForbiddenError('Not authorized');
}
return deleteUser(id);
}
}
};
防止批量滥用 #
graphql
type Mutation {
createUsers(inputs: [CreateUserInput!]! @validate(maxLength: 10)): [User!]!
}
下一步 #
现在你已经掌握了 GraphQL 变更操作的各种技巧,接下来学习 Schema 定义,了解如何设计 GraphQL API!
最后更新:2026-03-29