𝑻𝒆𝒏𝑪𝒍𝒂𝒘正在头脑风暴···
𝑻𝒆𝒏𝑲𝒊𝑺𝒆𝒀𝒂の𝑨𝒈𝒆𝒏𝒕助手
𝑻𝒆𝒏-𝒇𝒍𝒂𝒔𝒉

GraphQL 查询语言完全指南

GraphQL 是一种强类型的查询语言,让客户端精确控制需要的数据。本文将全面介绍 GraphQL 的核心概念、查询语法和最佳实践。

一、GraphQL 简介

1.1 什么是 GraphQL?

GraphQL 是由 Facebook 开源的 API 查询语言,允许客户端精确请求所需的数据,避免了传统 REST API 的过度获取或获取不足问题。

1.2 GraphQL 的特点

  1. 按需获取数据:客户端只请求需要的数据
  2. 强类型系统:严格的类型检查
  3. 单一接口:统一的数据查询接口
  4. 查询变异订阅:支持多种操作类型
  5. 高效查询:客户端可以精确控制数据结构

1.3 GraphQL vs REST

特性GraphQLREST
数据获取按需获取固定资源
接口单一端点多个端点
查询复杂度客户端控制服务端控制
过渡获取客户端决定固定响应
类型系统强类型轻量类型

二、核心概念

2.1 Schema(模式)

Schema 定义了 API 的数据结构和操作。

type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
}

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

type Query {
user(id: ID!): User
users: [User!]!
}

type Mutation {
createUser(name: String!, email: String!): User
}

type Subscription {
postCreated: Post
}

2.2 类型系统

基础类型

String   # 字符串
Int # 整数
Float # 浮点数
Boolean # 布尔值
ID # 唯一标识符

复杂类型

# 列表类型
[Int] # 整数列表
[String!] # 非空字符串列表
[User!] # 非空用户列表

# 非空类型
String! # 必填字符串
Int! # 必填整数

# 组合类型
User { # 对象类型
id: ID!
name: String!
}

# 枚举类型
enum Role {
ADMIN
EDITOR
USER
}

# 输入类型
input UserInput {
name: String!
email: String!
age: Int
}

2.3 查询操作类型

Query(查询)

# 获取单个用户
query GetUser {
user(id: "1") {
name
email
}
}

# 获取用户列表
query GetUsers {
users {
id
name
email
}
}

Mutation(变异)

# 创建用户
mutation CreateUser {
createUser(name: "张三", email: "zhang@example.com") {
id
name
email
}
}

Subscription(订阅)

# 订阅新帖子
subscription OnPostCreated {
postCreated {
title
content
}
}

三、查询语法

3.1 字段查询

# 基础查询
query {
user(id: "1") {
name
email
}
}

# 嵌套查询
query {
user(id: "1") {
name
email
posts {
title
content
author {
name
email
}
}
}
}

3.2 参数传递

# 参数
query GetUser($id: ID!, $includePosts: Boolean!) {
user(id: $id) {
name
email
${includePosts ? "posts { title }" : ""}
}
}

# 变量
{
"id": "1",
"includePosts": true
}

3.3 别名

# 别名
query {
admin: user(id: "1") {
name
email
}
editor: user(id: "2") {
name
email
}
}

3.4 片段

# 片段定义
fragment UserFields on User {
id
name
email
}

# 使用片段
query {
user(id: "1") {
...UserFields
}
}

# 复杂片段
fragment PostFields on Post {
id
title
content
author {
name
email
}
}

query {
user(id: "1") {
...UserFields
posts {
...PostFields
}
}
}

3.5 指令

# @include 和 @skip
query GetUser($includePosts: Boolean!) {
user(id: "1") {
name
email
${includePosts ? "posts { title }" : ""}
}
}

# 在查询中使用
query {
user(id: "1") {
name
email
@include(if: true) {
age
}
}
}

四、实战案例

4.1 用户查询

# 获取单个用户
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
avatar
bio
createdAt
updatedAt
}
}

# 获取用户及其文章
query GetUserWithPosts($id: ID!) {
user(id: $id) {
id
name
email
posts {
id
title
content
status
createdAt
author {
id
name
email
}
comments {
id
content
author {
id
name
}
}
}
}
}

4.2 分页查询

# 简单分页
query GetUsers($page: Int!, $limit: Int!) {
users(page: $page, limit: $limit) {
items {
id
name
email
}
total
page
limit
totalPages
}
}

# 使用连接
query GetUsersWithPagination($first: Int!, $after: String) {
users(first: $first, after: $after) {
edges {
cursor
node {
id
name
email
}
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
}
}

4.3 复杂查询

# 搜索用户
query SearchUsers($query: String!) {
searchUsers(query: $query) {
id
name
email
avatar
followersCount
followingCount
createdAt
updatedAt
}
}

# 统计数据
query GetStatistics {
usersCount
postsCount
commentsCount
todayUsersCount
todayPostsCount
}

# 排序查询
query GetUsersSorted($sortBy: String!, $order: String!) {
users(sortBy: $sortBy, order: $order) {
id
name
email
createdAt
}
}

五、错误处理

5.1 错误响应

{
"errors": [
{
"message": "用户不存在",
"locations": [{ "line": 2, "column": 3 }],
"path": ["user"]
}
]
}

5.2 错误处理

# 使用 try-catch
query {
user(id: "1") {
name
email
}
}

5.3 错误码

# 定义错误类型
type Error {
message: String!
code: String!
path: [String!]
}

# 在响应中使用
{
"errors": [
{
"message": "Invalid user ID",
"code": "INVALID_ID",
"path": ["user"]
}
]
}

六、最佳实践

6.1 查询优化

# 只请求需要的字段
query {
user(id: "1") {
name
email
avatar
bio
}
}

6.2 参数验证

# 输入类型验证
input UserInput {
name: String! @length(min: 3)
email: String! @email
age: Int @range(min: 18)
}

# 错误处理
mutation {
createUser(input: {
name: "张"
email: "invalid"
}) {
id
name
email
}
}

6.3 查询复杂度控制

// 设置查询复杂度限制
const complexity = {
getUser: 10,
getPosts: 20,
getComments: 5,
// ...
};

const maxComplexity = 1000;

6.4 安全性

// 认证中间件
const authenticate = (context) => {
if (!context.token) {
throw new Error('未认证');
}
// 验证 token
};

// 授权中间件
const authorize = (roles) => (context) => {
if (!roles.includes(context.user.role)) {
throw new Error('权限不足');
}
};

七、工具和库

7.1 GraphQL 工具

  • GraphQL Playground:交互式查询编辑器
  • GraphiQL:另一种查询编辑器
  • Apollo Studio:监控和分析工具

7.2 JavaScript 库

// Apollo Client
import { ApolloClient, InMemoryCache, gql } from '@apollo/client';

const client = new ApolloClient({
uri: 'http://localhost:4000/graphql',
cache: new InMemoryCache()
});

// 查询数据
const { data } = await client.query({
query: gql`
query GetUser($id: ID!) {
user(id: $id) {
name
email
}
}
`,
variables: { id: '1' }
});

八、总结

GraphQL 的核心优势:

  1. 按需获取数据
  2. 强类型系统
  3. 单一接口
  4. 高效查询

常用操作:

  • Query:获取数据
  • Mutation:修改数据
  • Subscription:实时更新

掌握 GraphQL,设计更高效的 API!