7.5 KiB
7.5 KiB
查询模式
本参考文档涵盖了编写高效 GraphQL 查询的模式。
目录
查询结构
基本查询
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
}
}
组成部分:
query— 操作类型GetUser— 操作名称($id: ID!)— 变量定义user(id: $id)— 带参数的字段{ id name email }— 选择集
多根字段查询
query GetDashboardData($userId: ID!) {
user(id: $userId) {
id
name
}
notifications(first: 5) {
id
message
}
stats {
totalPosts
totalComments
}
}
嵌套查询
query GetUserWithPosts($userId: ID!) {
user(id: $userId) {
id
name
posts(first: 10) {
edges {
node {
id
title
comments(first: 3) {
edges {
node {
id
body
}
}
}
}
}
}
}
}
字段选择
只请求需要的字段
# 用户卡片组件
query GetUserCard($id: ID!) {
user(id: $id) {
id
name
avatarUrl
# 如果不展示,不要请求 email、bio 等字段
}
}
始终包含 ID 字段
为可能缓存或重新获取的类型包含 id:
query GetPost($id: ID!) {
post(id: $id) {
id # 始终包含,用于缓存
title
author {
id # 包含,用于作者缓存条目
name
}
}
}
选择连接(Connection)
对于分页数据,按需请求:
query GetUserPosts($userId: ID!, $first: Int!, $after: String) {
user(id: $userId) {
id
posts(first: $first, after: $after) {
edges {
node {
id
title
excerpt
}
cursor # 仅在实现无限滚动时需要
}
pageInfo {
hasNextPage
endCursor
}
totalCount # 仅在展示总数时需要
}
}
}
别名
基本别名
在响应中重命名字段:
query GetUserNames($id: ID!) {
user(id: $id) {
userId: id
displayName: name
}
}
# 响应:{ user: { userId: "123", displayName: "John" } }
多次查询同一字段
query GetMultipleUsers {
admin: user(id: "1") {
id
name
}
moderator: user(id: "2") {
id
name
}
currentUser: user(id: "3") {
id
name
}
}
使用不同参数的别名
query GetPostsByStatus($userId: ID!) {
user(id: $userId) {
id
publishedPosts: posts(status: PUBLISHED, first: 5) {
edges {
node {
id
title
}
}
}
draftPosts: posts(status: DRAFT, first: 5) {
edges {
node {
id
title
}
}
}
}
}
指令
@include 指令
仅当条件为 true 时包含字段:
query GetUser($id: ID!, $includeEmail: Boolean!) {
user(id: $id) {
id
name
email @include(if: $includeEmail)
}
}
# 变量:{ id: "123", includeEmail: true }
# 返回 email 字段
# 变量:{ id: "123", includeEmail: false }
# 不返回 email 字段
@skip 指令
当条件为 true 时跳过字段:
query GetPost($id: ID!, $isPreview: Boolean!) {
post(id: $id) {
id
title
content @skip(if: $isPreview)
excerpt
}
}
在片段上使用指令
query GetUser($id: ID!, $expanded: Boolean!) {
user(id: $id) {
id
name
...UserDetails @include(if: $expanded)
}
}
fragment UserDetails on User {
bio
website
socialLinks {
platform
url
}
}
组合使用指令
query GetPost($id: ID!, $showComments: Boolean!, $hideAuthor: Boolean!) {
post(id: $id) {
id
title
author @skip(if: $hideAuthor) {
id
name
}
comments(first: 10) @include(if: $showComments) {
edges {
node {
id
body
}
}
}
}
}
查询命名
命名约定
| 用途 | 模式 | 示例 |
|---|---|---|
| 获取单个条目 | Get{Type} |
GetUser,GetPost |
| 获取列表 | List{Types} |
ListUsers,ListPosts |
| 搜索 | Search{Types} |
SearchUsers,SearchProducts |
| 为特定 UI 获取 | Get{Feature}Data |
GetDashboardData,GetProfilePage |
好的命名
query GetUserProfile($id: ID!) { ... }
query ListRecentPosts($first: Int!) { ... }
query SearchProducts($query: String!) { ... }
query GetOrderDetails($orderId: ID!) { ... }
query GetHomeFeed($userId: ID!) { ... }
避免泛化命名
# 避免
query Data { ... }
query Query1 { ... }
query FetchStuff { ... }
# 推荐
query GetCurrentUser { ... }
query ListActiveProjects { ... }
query SearchCustomers($query: String!) { ... }
查询组织
每个文件一个查询
src/
graphql/
queries/
GetUser.graphql
ListPosts.graphql
SearchProducts.graphql
# GetUser.graphql
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
}
}
与组件同目录放置
src/
components/
UserProfile/
UserProfile.tsx
UserProfile.graphql
UserProfile.test.tsx
导入并使用
// 使用 graphql-tag
import { gql } from "@apollo/client";
export const GET_USER = gql`
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}
`;
// 使用 .graphql 文件(需要加载器)
import { GetUserDocument } from "./UserProfile.generated";
性能优化
避免过度获取
只请求组件会用到的字段:
# 列表视图——最少字段
query ListPostsForIndex {
posts(first: 20) {
edges {
node {
id
title
excerpt
author { name }
}
}
}
}
# 详情视图——更多字段
query GetPostDetail($id: ID!) {
post(id: $id) {
id
title
content
publishedAt
author {
id
name
bio
avatarUrl
}
comments(first: 10) { ... }
}
}
使用分页
切勿获取无界列表:
# 避免
query GetAllPosts {
posts {
# 可能返回数千条
id
title
}
}
# 推荐
query GetPosts($first: Int = 20, $after: String) {
posts(first: $first, after: $after) {
edges {
node {
id
title
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
批量合并相关查询
在一次请求中获取相关数据:
# 替代多次查询
query GetDashboard($userId: ID!) {
user(id: $userId) {
id
name
}
recentPosts: posts(first: 5, orderBy: { field: CREATED_AT, direction: DESC }) {
edges {
node {
id
title
}
}
}
notifications(first: 10, unreadOnly: true) {
edges {
node {
id
message
}
}
}
}
对重复选择集使用片段
query GetPostsWithAuthors {
posts(first: 10) {
edges {
node {
id
title
author {
...AuthorInfo
}
}
}
}
featuredPost {
id
title
author {
...AuthorInfo
}
}
}
fragment AuthorInfo on User {
id
name
avatarUrl
}