跳转至

第二章:Schema 定义

类型系统

标量类型

# 内置标量类型
scalar Int      # 整数
scalar Float    # 浮点数
scalar String   # 字符串
scalar Boolean  # 布尔值
scalar ID       # 唯一标识符

# 自定义标量
scalar Date     # 日期
scalar DateTime # 日期时间
scalar JSON     # JSON 对象
scalar Upload   # 文件上传

对象类型

# 定义对象类型
type User {
  id: ID!
  name: String!
  email: String!
  age: Int
  isActive: Boolean!
  createdAt: DateTime!
  updatedAt: DateTime!
}

# 带描述的类型
"""
用户信息
"""
type User {
  """用户 ID"""
  id: ID!

  """用户名"""
  name: String!

  """邮箱地址"""
  email: String!
}

枚举类型

# 定义枚举
enum UserStatus {
  ACTIVE
  INACTIVE
  SUSPENDED
}

enum PostStatus {
  DRAFT
  PUBLISHED
  ARCHIVED
}

# 使用枚举
type User {
  id: ID!
  name: String!
  status: UserStatus!
}

接口类型

# 定义接口
interface Node {
  id: ID!
  createdAt: DateTime!
}

# 实现接口
type User implements Node {
  id: ID!
  createdAt: DateTime!
  name: String!
  email: String!
}

type Post implements Node {
  id: ID!
  createdAt: DateTime!
  title: String!
  content: String!
}

联合类型

# 定义联合类型
union SearchResult = User | Post

# 查询联合类型
query {
  search(query: "test") {
    ... on User {
      id
      name
      email
    }
    ... on Post {
      id
      title
      content
    }
  }
}

输入类型

Input 类型

# 定义输入类型
input CreateUserInput {
  name: String!
  email: String!
  age: Int
}

input UpdateUserInput {
  name: String
  email: String
  age: Int
}

input UserFilter {
  status: UserStatus
  name: String
  email: String
}

# 使用输入类型
type Mutation {
  createUser(input: CreateUserInput!): User!
  updateUser(id: ID!, input: UpdateUserInput!): User!
  users(filter: UserFilter): [User!]!
}

分页输入

# 分页输入
input PaginationInput {
  page: Int = 1
  pageSize: Int = 10
}

# 排序输入
input SortInput {
  field: String!
  order: SortOrder = ASC
}

enum SortOrder {
  ASC
  DESC
}

输出类型

分页输出

# 分页信息
type PageInfo {
  page: Int!
  pageSize: Int!
  total: Int!
  totalPages: Int!
  hasNextPage: Boolean!
  hasPreviousPage: Boolean!
}

# 分页结果
type UserConnection {
  data: [User!]!
  pageInfo: PageInfo!
}

# 查询
type Query {
  users(pagination: PaginationInput): UserConnection!
}

响应包装

# 通用响应
type Response {
  success: Boolean!
  message: String
  code: Int
}

# 带数据的响应
type UserResponse {
  success: Boolean!
  message: String
  data: User
}

# 错误响应
type ErrorResponse {
  success: Boolean!
  message: String!
  code: Int!
  errors: [FieldError!]
}

type FieldError {
  field: String!
  message: String!
}

指令

内置指令

# @skip - 条件跳过
query ($withPosts: Boolean!) {
  user(id: "1") {
    name
    posts @skip(if: $withPosts) {
      title
    }
  }
}

# @include - 条件包含
query ($withPosts: Boolean!) {
  user(id: "1") {
    name
    posts @include(if: $withPosts) {
      title
    }
  }
}

# @deprecated - 废弃字段
type User {
  id: ID!
  name: String!
  email: String!
  username: String @deprecated(reason: "Use 'name' instead")
}

自定义指令

# 定义指令
directive @auth(requires: Role = USER) on FIELD_DEFINITION

enum Role {
  ADMIN
  USER
}

# 使用指令
type Query {
  user(id: ID!): User @auth(requires: USER)
  adminData: String @auth(requires: ADMIN)
}

Schema 组织

模块化

# user.graphql
extend type Query {
  user(id: ID!): User
  users: [User!]!
}

extend type Mutation {
  createUser(input: CreateUserInput!): User!
  updateUser(id: ID!, input: UpdateUserInput!): User!
  deleteUser(id: ID!): Boolean!
}

type User {
  id: ID!
  name: String!
  email: String!
}

# post.graphql
extend type Query {
  post(id: ID!): Post
  posts: [Post!]!
}

extend type Mutation {
  createPost(input: CreatePostInput!): Post!
}

type Post {
  id: ID!
  title: String!
  content: String!
  author: User!
}

合并 Schema

// JavaScript 合并
const { mergeTypeDefs } = require('@graphql-tools/merge');

const userSchema = fs.readFileSync('user.graphql', 'utf-8');
const postSchema = fs.readFileSync('post.graphql', 'utf-8');

const typeDefs = mergeTypeDefs([userSchema, postSchema]);

小结

Schema 定义要点:

  • 类型系统:标量、对象、枚举、接口、联合
  • 输入类型:Input、分页、排序
  • 输出类型:分页、响应包装
  • 指令:内置指令、自定义指令
  • Schema 组织:模块化、合并

下一章我们将学习 Query 查询。