GraphQL API
GraphQL API 允许通过 Strapi 的 GraphQL 插件 对 内容类型 执行查询和变更。结果可以被 过滤、排序 和 分页。
🌐 The GraphQL API allows performing queries and mutations to interact with the content-types through Strapi's GraphQL plugin. Results can be filtered, sorted and paginated.
要使用 GraphQL API,请安装 GraphQL 插件:
🌐 To use the GraphQL API, install the GraphQL plugin:
- Yarn
- NPM
yarn add @strapi/plugin-graphql
npm install @strapi/plugin-graphql
安装完成后,GraphQL playground 可通过 /graphql URL 访问,并可用于交互式构建查询和变更操作,以及阅读针对你的内容类型定制的文档:
🌐 Once installed, the GraphQL playground is accessible at the /graphql URL and can be used to interactively build your queries and mutations and read documentation tailored to your content-types:

GraphQL 插件只公开一个处理所有查询和变更的端点。默认端点是 /graphql,并在 插件配置文件 中定义:
🌐 The GraphQL plugin exposes only one endpoint that handles all queries and mutations. The default endpoint is /graphql and is defined in the plugins configuration file:
export default {
shadowCRUD: true,
endpoint: '/graphql', // <— single GraphQL endpoint
subscriptions: false,
maxLimit: -1,
apolloServer: {},
v4CompatibilityMode: process.env.STRAPI_GRAPHQL_V4_COMPATIBILITY_MODE ?? false,
};
GraphQL API 不支持媒体上传。请使用 REST API POST /upload 端点 进行所有文件上传,并使用返回的信息在内容类型中链接它。你仍然可以使用 updateUploadFile 和 deleteUploadFile 变更通过媒体文件 id 更新或删除已上传的文件(参见 媒体文件的变更)。
🌐 The GraphQL API does not support media upload. Use the REST API POST /upload endpoint for all file uploads and use the returned info to link to it in content types. You can still update or delete uploaded files with the updateUploadFile and deleteUploadFile mutations using media files id (see mutations on media files).
documentId onlyGraphQL API 仅使用 documentId 字段公开文档。之前的数字 id 在这里不再可用,尽管它仍然通过 REST API 返回以保持向后兼容性(详见 breaking change)。
🌐 The GraphQL API exposes documents using only the documentId field. The previous numeric id is no longer available here, although it is still returned by the REST API for backward compatibility (see breaking change for details).
查询
🌐 Queries
GraphQL 中的查询用于获取数据而不修改数据。
🌐 Queries in GraphQL are used to fetch data without modifying it.
当将内容类型添加到你的项目时,2 个自动生成的 GraphQL 查询将添加到你的架构中,以内容类型的单数和复数 API ID 命名,如下例所示:
🌐 When a content-type is added to your project, 2 automatically generated GraphQL queries are added to your schema, named after the content-type's singular and plural API IDs, as in the following example:
| 内容类型显示名称 | 单数 API ID | 复数 API ID ||----------------|-----------------|---------------|| 餐厅 | restaurant | restaurants |
单数 API ID 与复数 API ID:
在内容类型生成器中创建内容类型时,会定义单数 API ID 和复数 API ID 值,并且可以在管理面板中编辑内容类型时找到(参见 用户指南)。你可以在创建内容类型时定义自定义 API ID,但之后无法修改这些 ID。
🌐 Singular API ID and Plural API ID values are defined when creating a content-type in the Content-Type Builder, and can be found while editing a content-type in the admin panel (see User Guide). You can define custom API IDs while creating the content-type, but these can not modified afterwards.


获取单个文档
🌐 Fetch a single document
可以通过它们的 documentId 获取文档 。
{
restaurant(documentId: "a1b2c3d4e5d6f7g8h9i0jkl") {
name
description
}
}
获取多个文档
🌐 Fetch multiple documents
要获取多个文档 你可以使用简单的、扁平的查询或 Relay-style 查询:
扁平查询只返回每个文档中请求 的字段。Relay 风格查询以 _connection 结尾,并返回一个 nodes 数组以及一个 pageInfo 对象。当你需要分页元数据时,请使用 Relay 风格查询。
🌐 Flat queries return only the requested fields for each document. Relay-style queries end with _connection and return a nodes array together with a pageInfo object. Use Relay-style queries when you need pagination metadata.
- Flat queries
- Relay-style queries
要获取多个文档,你可以使用如下所示的扁平查询:
🌐 To fetch multiple documents you can use flat queries like the following:
restaurants {
documentId
title
}
关系也可以通过文档服务 API 连接、断开和设置,就像 REST API 一样(有关示例,请参阅 XX1)。
🌐 Relay-style queries can be used to fetch multiple documents and return meta information:
{
restaurants_connection {
nodes {
documentId
name
}
pageInfo {
pageSize
page
pageCount
total
}
}
}
获取关系
🌐 Fetch relations
你可以在你的扁平查询或你的 Relay-style 查询中请求包含关联数据:
- Flat queries
- Relay-style queries
以下示例获取所有“Restaurant”内容类型的文档,并且对于每个文档,还返回与“Category”内容类型的多对多关系的一些字段:
🌐 The following example fetches all documents from the "Restaurant" content-type, and for each of them, also returns some fields for the many-to-many relation with the "Category" content-type:
{
restaurants {
documentId
name
description
# categories is a many-to-many relation
categories {
documentId
name
}
}
}
以下示例使用 Relay 风格的查询从 “Restaurant” 内容类型中获取所有文档,并且对于每个餐厅,还返回与 “Category” 内容类型的多对多关系的一些字段:
🌐 The following example fetches all documents from the "Restaurant" content-type using a Relay-style query, and for each restaurant, also returns some fields for the many-to-many relation with the "Category" content-type:
{
restaurants_connection {
nodes {
documentId
name
description
# categories is a many-to-many relation
categories_connection {
nodes {
documentId
name
}
}
}
pageInfo {
page
pageCount
pageSize
total
}
}
}
目前,pageInfo 仅适用于一级文档。Strapi 的未来版本可能会为关系实现 pageInfo。
🌐 For now, pageInfo only works for documents at the first level. Future implementations of Strapi might implement pageInfo for relations.
pageInfo 的可能用例:
这个可行:
{
restaurants_connection {
nodes {
documentId
name
description
# many-to-many relation
categories_connection {
nodes {
documentId
name
}
}
}
pageInfo {
page
pageCount
pageSize
total
}
}
}
这不起作用:
{
restaurants_connection {
nodes {
documentId
name
description
# many-to-many relation
categories_connection {
nodes {
documentId
name
}
# not supported
pageInfo {
page
pageCount
pageSize
total
}
}
}
pageInfo {
page
pageCount
pageSize
total
}
}
}}
获取媒体字段
🌐 Fetch media fields
媒体字段内容的获取方式与其他属性一样。
🌐 Media fields content is fetched just like other attributes.
以下示例获取“Restaurants”内容类型中附加到每个文档的每个 cover 媒体字段的 url 属性值:
🌐 The following example fetches the url attribute value for each cover media field attached to each document from the "Restaurants" content-type:
{
restaurants {
images {
documentId
url
}
}
}
对于多个媒体字段,你可以使用扁平查询或 Relay-style 查询:
- Flat queries
- Relay-style queries
以下示例从“餐厅”内容类型中找到的 images 多媒体字段获取一些属性:
🌐 The following example fetches some attributes from the images multiple media field found in the "Restaurant" content-type:
{
restaurants {
images_connection {
nodes {
documentId
url
}
}
}
}
以下示例使用 Relay 风格的查询从“Restaurant”内容类型中的 images 多媒体字段获取一些属性:
🌐 The following example fetches some attributes from the images multiple media field found in the "Restaurant" content-type using a Relay-style query:
{
restaurants {
images_connection {
nodes {
documentId
url
}
}
}
}
目前,pageInfo 仅适用于文档。未来版本的 Strapi 可能也会在媒体字段 _connection 上实现 pageInfo。
🌐 For now, pageInfo only works for documents. Future implementations of Strapi might implement pageInfo for the media fields _connection too.
获取组件
🌐 Fetch components
组件内容的获取方式与其他属性一样。
🌐 Components content is fetched just like other attributes.
以下示例获取每个文档中添加的每个 closingPeriod 组件的 label、start_date 和 end_date 属性值,这些文档来自“餐馆”内容类型:
🌐 The following example fetches the label, start_date, and end_date attributes values for each closingPeriod component added to each document from the "Restaurants" content-type:
{
restaurants {
closingPeriod {
label
start_date
end_date
}
}
}
获取动态区域数据
🌐 Fetch dynamic zone data
动态区域是在 GraphQL 中的联合类型,因此你需要使用 fragments (即使用 ...on)来查询字段,并将组件名称(使用 ComponentCategoryComponentname 语法)传递给 `__typename`:
以下示例获取可以添加到“dz”动态区域的“Default”组件类别中“Closingperiod”组件的 label 属性的数据:
🌐 The following example fetches data for the label attribute of a "Closingperiod" component from the "Default" components category that can be added to the "dz" dynamic zone:
{
restaurants {
dz {
__typename
...on ComponentDefaultClosingperiod {
# define which attributes to return for the component
label
}
}
}
}
获取草稿或已发布的版本
🌐 Fetch draft or published versions
如果内容类型启用了 Draft & Publish 功能,你可以在查询中添加 status 参数以获取文档的草稿或已发布版本 :
query Query($status: PublicationStatus) {
restaurants(status: DRAFT) {
documentId
name
publishedAt # should return null
}
}
query Query($status: PublicationStatus) {
restaurants(status: PUBLISHED) {
documentId
name
publishedAt
}
}
聚合
🌐 Aggregations
聚合可以用于计算统计量,例如计数、总和或分组总计,而无需单独获取每个文档。聚合通过 Relay-style 连接查询公开:每种集合类型在其<plural>_connection查询下都包含一个aggregate字段。
{
restaurants_connection(filters: { categories: { documentId: { eq: "food-trucks" } } }) {
aggregate {
count
}
}
}
聚合遵循与父查询相同的筛选条件、语言环境、发布状态和权限。例如,在连接上设置 locale: "fr" 或 status: DRAFT 会将聚合限制为那些文档,并且用户只能聚合他们被允许阅读的内容。
🌐 Aggregations follow the same filters, locale, publication status, and permissions as the parent query. For example, setting locale: "fr" or status: DRAFT on the connection limits the aggregation to those documents, and users can only aggregate content they are allowed to read.
下表列出了所有受支持的聚合运算符:
🌐 The table below lists all supported aggregation operators:
| 操作符 | 描述 | 支持的字段类型 || --- | --- | --- || count | 返回匹配查询的文档数量。 | 所有内容类型 || avg | 计算每个数值字段的算术平均值。 | 数字、整数、小数 || sum | 计算每个数值字段的总和 。 | 数字、整数、小数 || min | 返回每个字段的最小值。 | 数字、整数、小数、日期、日期时间 || max | 返回每个字段的最大值。 | 数字、整数、小数、日期、日期时间 || groupBy | 按唯一值对结果进行分组,并为每个分组提供嵌套聚合。 | 标量字段(字符串、数字、布尔值、日期、日期时间)、关联字段 |
Strapi 会忽略 avg、sum、min 和 max 的 null 值。在聚合关系时,操作符会在目标文档上运行,并且仍然遵守其语言环境和权限。
🌐 Strapi ignores null values for avg, sum, min, and max. When aggregating relations, the operators run on the target documents and still respect their locales and permissions.
聚合在服务器端运行,因此通常比在客户端下载和处理大量结果集更快。然而,复杂的 groupBy 树和宽投影仍可能开销较大。请使用过滤器来限制数据集,并考虑相应设置 depthLimit 和 amountLimit 值(参见 可用选项)以保护你的 API。诸如 You are not allowed to perform this action 的错误通常意味着请求者在目标集合上缺少 Read 权限。
🌐 Aggregations operate server-side, so they are generally faster than downloading and processing large result sets on the client. However, complex groupBy trees and wide projections can still be expensive. Use filters to restrict the data set and consider setting up depthLimit and amountLimit values accordingly (see available options) to protect your API. Errors such as You are not allowed to perform this action usually mean the requester lacks the Read permission on the target collection.
在一个请求中汇总多个指标
🌐 Aggregate multiple metrics in one request
可以组合聚合,以便一次网络往返返回多个指标:
🌐 Aggregations can be combined so that one network round trip returns several metrics:
{
restaurants_connection(filters: { takeAway: { eq: true } }) {
aggregate {
avg {
delivery_time
}
min {
price_range
}
max {
price_range
}
}
}
}
分组结果
🌐 Group results
使用 groupBy 来推导分组指标,同时可以选择在每个组内进一步链式聚合。每个组都会展示唯一的 key 以及一个嵌套的连接,可用于下钻或统计分组项:
🌐 Use groupBy to derive grouped metrics while optionally chaining further aggregations inside each group. Each group exposes the unique key and a nested connection that can be used for drilling down or counting the grouped items:
{
restaurants_connection {
aggregate {
groupBy {
categories {
key
connection {
aggregate {
count
}
}
}
}
}
}
}
组继承顶层过滤器。要进一步细化特定组,请在嵌套的 connection 上应用过滤器。
🌐 Groups inherit the top-level filters. To further refine a specific group, apply filters on the nested connection.
与分页和排序结合
🌐 Combine with pagination and sorting
聚合运行在匹配查询过滤条件的整个结果集上,而不仅仅是当前页面。当请求包含分页参数和聚合时,nodes 中的文档遵循分页限制,但 aggregate 内的值会忽略 pageSize 或 limit,因此它们描述的是整个集合。你仍然可以添加排序以对返回的带聚合结果的文档进行排序。
🌐 Aggregations run on the entire result set that matches the query filters, not only on the current page. When a request includes pagination arguments and aggregations, the documents in nodes follow the pagination limits, but the values inside aggregate ignore pageSize or limit so they describe the whole set. You can still add sorting to order the documents returned with the aggregation results.
{
restaurants_connection(
filters: { takeAway: { eq: true } }
pagination: { page: 2, pageSize: 5 }
sort: "name:asc"
) {
nodes {
documentId
name
rating
}
pageInfo {
page
pageSize
total
}
aggregate {
count
avg {
rating
}
}
}
}
突变
🌐 Mutations
GraphQL 中的突变用于修改数据(例如创建、更新和删除数据)。
🌐 Mutations in GraphQL are used to modify data (e.g. create, update, and delete data).
当将内容类型添加到你的项目时,将向你的架构添加 3 个自动生成的 GraphQL 修改,用于创建、更新和删除文档 。
例如,对于“餐厅”内容类型,会生成以下变更:
🌐 For instance, for a "Restaurant" content-type, the following mutations are generated:
| 用例 | 单一 API ID ||---------------------------------------------|---------------------|| 创建一个新的“餐厅”文档 | createRestaurant || 更新一个现有的“餐厅”餐厅 | updateRestaurant || 删除一个现有的“餐厅”餐厅 | deleteRestaurant |
创建新文档
🌐 Create a new document
在创建新文档时,data 参数将具有与你的内容类型特定相关的输入类型。
🌐 When creating new documents, the data argument will have an associated input type that is specific to your content-type.
例如,如果你的 Strapi 项目包含“餐厅”内容类型,你将拥有以下内容:
🌐 For instance, if your Strapi project contains the "Restaurant" content-type, you will have the following:
| 突变 | 参数 | 输入类型 ||--------------------|------------------|--------------------|| createRestaurant | data | RestaurantInput! |
以下示例为“餐厅”内容类型创建一个新文档,并返回其 name 和 documentId:
🌐 The following example creates a new document for the "Restaurant" content-type and returns its name and documentId:
mutation CreateRestaurant($data: RestaurantInput!) {
createRestaurant(data: {
name: "Pizzeria Arrivederci"
}) {
name
documentId
}
}
创建新文档时,会自动生成一个 documentId。
🌐 When creating a new document, a documentId is automatically generated.
突变的实现也支持关系属性。例如,你可以创建一个新的“类别”,并通过编写如下查询,将许多“餐馆”(使用它们的 documentId)附加到它上面:
🌐 The implementation of the mutations also supports relational attributes. For example, you can create a new "Category" and attach many "Restaurants" (using their documentId) to it by writing your query like follows:
mutation CreateCategory {
createCategory(data: {
Name: "Italian Food"
restaurants: ["a1b2c3d4e5d6f7g8h9i0jkl", "bf97tfdumkcc8ptahkng4puo"]
}) {
documentId
Name
restaurants {
documentId
name
}
}
}
如果你的内容类型启用了国际化 (i18n) 功能,你可以为特定的区域创建文档(参见 创建新的本地化文档)。
🌐 If the Internationalization (i18n) feature is enabled for your content-type, you can create a document for a specific locale (see create a new localized document).