Skip to main content

GraphQL API

Page summary:

GraphQL API 允许对内容类型进行查询和修改,并支持过滤、排序和分页。它使用 documentId 作为唯一标识符,并提供单数和复数查询,支持关系、媒体字段、组件、动态区域和本地化。

🌐 The GraphQL API allows querying and mutating content-types with filtering, sorting, and pagination. It uses documentId as the unique identifier and provides singular and plural queries with support for relations, media fields, components, dynamic zones, and localization.

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.

Prerequisites

要使用 GraphQL API,请安装 GraphQL 插件:

🌐 To use the GraphQL API, install the GraphQL plugin:

terminal
yarn add @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 playground use exampleGraphQL playground use example

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:

/config/plugins.js|ts
  export default {
shadowCRUD: true,
endpoint: '/graphql', // <— single GraphQL endpoint
subscriptions: false,
maxLimit: -1,
apolloServer: {},
v4CompatibilityMode: process.env.STRAPI_GRAPHQL_V4_COMPATIBILITY_MODE ?? false,
};
No GraphQL API to upload media files

GraphQL API 不支持媒体上传。请使用 REST API POST /upload 端点 进行所有文件上传,并使用返回的信息在内容类型中链接它。你仍然可以使用 updateUploadFiledeleteUploadFile 变更通过媒体文件 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).

Caution
documentId only

GraphQL 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
餐厅restaurantrestaurants
单数 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.

Screenshot of the Content-Type Builder to retrieve singular and plural API IDsScreenshot of the Content-Type Builder to retrieve singular and plural API IDs

获取单个文档

🌐 Fetch a single document

可以通过它们的 documentId 获取文档

A document in Strapi 5 is an API-only concept which represents all the variations of content (for different locales, for the draft and published versions) for a given entry found in the Content Manager.

More details can be found in the Documents introduction.

Example query: Find a restaurant with its documentId
{
restaurant(documentId: "a1b2c3d4e5d6f7g8h9i0jkl") {
name
description
}
}

获取多个文档

🌐 Fetch multiple documents

要获取多个文档

A document in Strapi 5 is an API-only concept which represents all the variations of content (for different locales, for the draft and published versions) for a given entry found in the Content Manager.

More details can be found in the Documents introduction.

你可以使用简单的、扁平的查询或 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.

要获取多个文档,你可以使用如下所示的扁平查询:

🌐 To fetch multiple documents you can use flat queries like the following:

Example query: Find all restaurants
restaurants {
documentId
title
}

获取关系

🌐 Fetch relations

你可以在你的扁平查询或你的 Relay-style 查询中请求包含关联数据:

以下示例获取所有“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:

Example query: Find all restaurants and their associated categories
{
restaurants {
documentId
name
description
# categories is a many-to-many relation
categories {
documentId
name
}
}
}

获取媒体字段

🌐 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 查询:

以下示例从“餐厅”内容类型中找到的 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
}
}
}
}

获取组件

🌐 Fetch components

组件内容的获取方式与其他属性一样。

🌐 Components content is fetched just like other attributes.

以下示例获取每个文档中添加的每个 closingPeriod 组件的 labelstart_dateend_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 参数以获取文档的草稿或已发布版本

A document in Strapi 5 is an API-only concept which represents all the variations of content (for different locales, for the draft and published versions) for a given entry found in the Content Manager.

More details can be found in the Documents introduction.

Example: Fetch draft versions of documents
query Query($status: PublicationStatus) {
restaurants(status: DRAFT) {
documentId
name
publishedAt # should return null
}
}
Example: Fetch published versions of documents
query Query($status: PublicationStatus) {
restaurants(status: PUBLISHED) {
documentId
name
publishedAt
}
}

使用 publicationFilter 过滤

🌐 Filter with publicationFilter

如果启用了 Draft & Publish 功能,你可以在内置集合和单类型查询中添加 publicationFilter 参数。它根据草稿版本和已发布版本之间的关系筛选文档:例如,从未发布的草稿,或者自上次发布以来被修改的条目。GraphQL 通过 PublicationFilter 枚举暴露与 REST API 和文档服务 API 相同的值。

🌐 If the Draft & Publish feature is enabled, you can add a publicationFilter argument to built-in collection and single-type queries. It filters documents by the relationship between their draft and published versions: for example, drafts that were never published, or entries modified since they were last published. GraphQL exposes the same values as the REST API and the Document Service API through the PublicationFilter enum.

publicationFilter 首先选择文档组;然后 status 参数决定每个结果返回其草稿行还是已发布行。

Caution

当省略 status 时,GraphQL 会在应用 publicationFilter 之前默认使用 PUBLISHED(与 REST 相同)。草稿类值如 NEVER_PUBLISHED 不会返回结果,除非你传入 status: DRAFT

🌐 When status is omitted, GraphQL defaults to PUBLISHED before applying publicationFilter (same as REST). Draft-only values such as NEVER_PUBLISHED return no results unless you pass status: DRAFT.

Example: Fetch never-published draft documents
query Query($status: PublicationStatus, $publicationFilter: PublicationFilter) {
restaurants(status: DRAFT, publicationFilter: NEVER_PUBLISHED) {
documentId
name
publishedAt
}
}
Example: Modified documents with default PUBLISHED status
query Query {
restaurants(publicationFilter: MODIFIED) {
documentId
name
publishedAt
}
}

可用的枚举值:

🌐 Available enum values:

GraphQL 枚举文档服务 / REST 值
NEVER_PUBLISHEDnever-published
HAS_PUBLISHED_VERSIONhas-published-version
MODIFIEDmodified
UNMODIFIEDunmodified
NEVER_PUBLISHED_DOCUMENTnever-published-document
HAS_PUBLISHED_VERSION_DOCUMENThas-published-version-document
PUBLISHED_WITHOUT_DRAFTpublished-without-draft仅诊断
PUBLISHED_WITH_DRAFTpublished-with-draft仅诊断

要了解更多信息,请参阅文档服务 API 页面上的用例和接受的值

🌐 To learn more, see the use cases and accepted values on the Document Service API page.

突变

🌐 Mutations

GraphQL 中的突变用于修改数据(例如创建、更新和删除数据)。

🌐 Mutations in GraphQL are used to modify data (e.g. create, update, and delete data).

当将内容类型添加到你的项目时,将向你的架构添加 3 个自动生成的 GraphQL 修改,用于创建、更新和删除文档

A document in Strapi 5 is an API-only concept which represents all the variations of content (for different locales, for the draft and published versions) for a given entry found in the Content Manager.

More details can be found in the Documents introduction.

例如,对于“餐厅”内容类型,会生成以下变更:

🌐 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:

突变参数输入类型
createRestaurantdataRestaurantInput!

以下示例为“餐厅”内容类型创建一个新文档,并返回其 namedocumentId

🌐 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
}
}
}
Tip

如果你的内容类型启用了国际化 (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).

更新现有文档

🌐 Update an existing document

在更新现有文档

A document in Strapi 5 is an API-only concept which represents all the variations of content (for different locales, for the draft and published versions) for a given entry found in the Content Manager.

More details can be found in the Documents introduction.

时,传递包含新内容的 documentIddata 对象。data 参数将具有与你的内容类型特定的关联输入类型。

例如,如果你的 Strapi 项目包含“餐厅”内容类型,你将拥有以下内容:

🌐 For instance, if your Strapi project contains the "Restaurant" content-type, you will have the following:

突变参数输入类型
updateRestaurantdataRestaurantInput!

例如,以下示例会更新一个现有的“餐厅”内容类型的文档,并给它一个新名称:

🌐 For instance, the following example updates an existing document from the "Restaurants" content-type and give it a new name:

mutation UpdateRestaurant($documentId: ID!, $data: RestaurantInput!) {
updateRestaurant(
documentId: "bf97tfdumkcc8ptahkng4puo",
data: { name: "Pizzeria Amore" }
) {
documentId
name
}
}
Tip

如果为你的内容类型启用了国际化 (i18n) 功能,你可以为特定的区域创建文档(参见 i18n 文档)。

🌐 If the Internationalization (i18n) feature is enabled for your content-type, you can create a document for a specific locale (see i18n documentation).

更新关系

🌐 Update relations

你可以通过传递一个 documentId 或一个 documentId 数组(取决于关系类型)来更新关系属性。

🌐 You can update relational attributes by passing a documentId or an array of documentId (depending on the relation type).

例如,以下示例会更新“Restaurant”内容类型的文档,并通过 categories 关联字段向“Category”内容类型的文档添加关联:

🌐 For instance, the following example updates a document from the "Restaurant" content-type and adds a relation to a document from the "Category" content-type through the categories relation field:

mutation UpdateRestaurant($documentId: ID!, $data: RestaurantInput!) {
updateRestaurant(
documentId: "slwsiopkelrpxpvpc27953je",
data: { categories: ["kbbvj00fjiqoaj85vmylwi17"] }
) {
documentId
name
categories {
documentId
Name
}
}
}

删除文档

🌐 Delete a document

要删除文档

A document in Strapi 5 is an API-only concept which represents all the variations of content (for different locales, for the draft and published versions) for a given entry found in the Content Manager.

More details can be found in the Documents introduction.

,传入其 documentId

mutation DeleteRestaurant {
deleteRestaurant(documentId: "a1b2c3d4e5d6f7g8h9i0jkl") {
documentId
}
}
Tip

如果你的内容类型启用了国际化 (i18n) 功能,你可以删除文档的特定本地化版本(参见 i18n 文档)。

🌐 If the Internationalization (i18n) feature is enabled for your content-type, you can delete a specific localized version of a document (see i18n documentation).

媒体文件的修改

🌐 Mutations on media files

Caution

目前,媒体字段上的变更使用 Strapi v4 id,而不是 Strapi 5 documentId,作为媒体文件的唯一标识符。

🌐 Currently, mutations on media fields use Strapi v4 id, not Strapi 5 documentId, as unique identifiers for media files.

媒体字段的变更使用文件 id。然而,Strapi 5 中的 GraphQL API 查询不再返回 id。可以找到媒体文件 id

🌐 Media fields mutations use files id. However, GraphQL API queries in Strapi 5 do not return id anymore. Media files id can be found:

  • 也可以在管理员面板的媒体库中,

    Media Library screenshot highlighting how to find a media file idMedia Library screenshot highlighting how to find a media file id
  • 或者通过发送 REST API GET 请求来填充媒体文件,因为 REST API 请求目前会返回媒体文件的 iddocumentId

更新已上传的媒体文件

🌐 Update an uploaded media file

在更新已上传的媒体文件时,传入媒体的 id(而不是它的 documentId)以及包含新内容的 info 对象。info 参数将具有与媒体文件特定相关的输入类型。

🌐 When updating an uploaded media file, pass the media's id (not its documentId) and the info object containing new content. The info argument will has an associated input type that is specific to media files.

例如,如果你的 Strapi 项目包含“餐厅”内容类型,你将拥有以下内容:

🌐 For instance, if your Strapi project contains the "Restaurant" content-type, you will have the following:

突变参数输入类型
updateUploadFileinfoFileInfoInput!

例如,下面的示例更新了 id 为 3 的媒体文件的 alternativeText 属性:

🌐 For instance, the following example updates the alternativeText attribute for a media file whose id is 3:

mutation Mutation($updateUploadFileId: ID!, $info: FileInfoInput) {
updateUploadFile(
id: 3,
info: {
alternativeText: "New alt text"
}
) {
documentId
url
alternativeText
}
}
Tip

如果上传变更返回禁止访问错误,请确保为上传插件设置了适当的权限(参见用户指南)。

🌐 If upload mutations return a forbidden access error, ensure proper permissions are set for the Upload plugin (see User Guide).

删除已上传的媒体文件

🌐 Delete an uploaded media file

在删除已上传的媒体文件时,传递媒体的 id(而不是它的 documentId)。

🌐 When deleting an uploaded media file, pass the media's id (not its documentId).

Example: Delete the media file with id 4
mutation DeleteUploadFile($deleteUploadFileId: ID!) {
deleteUploadFile(id: 4) {
documentId # return its documentId
}
}
Tip

如果上传变更返回禁止访问错误,请确保为上传插件设置了适当的权限(参见用户指南)。

🌐 If upload mutations return a forbidden access error, ensure proper permissions are set for the Upload plugin (see User Guide).

过滤器

🌐 Filters

查询可以接受带有以下语法的 filters 参数:

🌐 Queries can accept a filters parameter with the following syntax:

filters: { field: { operator: value } }

多个筛选器可以组合在一起,逻辑运算符(andornot)也可以使用,并且接受对象数组。当多个字段条件被组合时,它们会默认使用 and 连接。

🌐 Multiple filters can be combined together, and logical operators (and, or, not) can also be used and accept arrays of objects. When multiple field conditions are combined, they are implicitly joined with and.

Tip

andornot 运算符可以互相嵌套。

可以使用以下运算符:

🌐 The following operators are available:

操作符描述
eq等于
eqi等于,忽略大小写
ne不等于
nei不等于,忽略大小写
lt小于
lte小于或等于
gt大于
gte大于或等于
in包含于数组中
notIn不包含于数组中
contains包含,区分大小写
notContains不包含,区分大小写
containsi包含,忽略大小写
notContainsi不包含,忽略大小写
null为空
notNull不为空
between介于之间
startsWith以...开头
endsWith以...结尾
and逻辑 and
or逻辑 or
not逻辑 not
Simple examples for comparison operators (eq, ne, lt, lte, gt, gte, between)
# eq - returns restaurants with the exact name "Biscotte"
{
restaurants(filters: { name: { eq: "Biscotte" } }) {
name
}
}

# eqi - returns restaurants whose name equals "Biscotte",
# comparison is case-insensitive
{
restaurants(filters: { name: { eqi: "Biscotte" } }) {
name
}
}

# ne - returns restaurants whose name is not "Biscotte"
{
restaurants(filters: { name: { ne: "Biscotte" } }) {
name
}
}

# nei - returns restaurants whose name is not "Biscotte",
# comparison is case-insensitive
{
restaurants(filters: { name: { nei: "Biscotte" } }) {
name
}
}

# lt - returns restaurants with averagePrice less than 20
{
restaurants(filters: { averagePrice: { lt: 20 } }) {
name
}
}

# lte - returns restaurants with averagePrice less than or equal to 20
{
restaurants(filters: { averagePrice: { lte: 20 } }) {
name
}
}

# gt - returns restaurants with averagePrice greater than 20
{
restaurants(filters: { averagePrice: { gt: 20 } }) {
name
}
}

# gte - returns restaurants with averagePrice greater than or equal to 20
{
restaurants(filters: { averagePrice: { gte: 20 } }) {
name
}
}

# between - returns restaurants with averagePrice between 10 and 30
{
restaurants(filters: { averagePrice: { between: [10, 30] } }) {
name
}
}
Simple examples for membership operators (in, notIn)
# in - returns restaurants with category either "pizza" or "burger"
{
restaurants(filters: { category: { in: ["pizza", "burger"] } }) {
name
}
}

# notIn - returns restaurants whose category is neither "pizza" nor "burger"
{
restaurants(filters: { category: { notIn: ["pizza", "burger"] } }) {
name
}
}
Simple examples for string matching operators (contains, notContains, containsi, notContains, startsWith, endsWith)
# contains - returns restaurants whose name contains "Pizzeria"
{
restaurants(filters: { name: { contains: "Pizzeria" } }) {
name
}
}

# notContains - returns restaurants whose name does NOT contain "Pizzeria"
{
restaurants(filters: { name: { notContains: "Pizzeria" } }) {
name
}
}

# containsi - returns restaurants whose name contains "pizzeria" (case‑insensitive)
{
restaurants(filters: { name: { containsi: "pizzeria" } }) {
name
}
}

# notContainsi - returns restaurants whose name does NOT contain "pizzeria" (case‑insensitive)
{
restaurants(filters: { name: { notContainsi: "pizzeria" } }) {
name
}
}

# startsWith - returns restaurants whose name starts with "Pizza"
{
restaurants(filters: { name: { startsWith: "Pizza" } }) {
name
}
}

# endsWith - returns restaurants whose name ends with "Inc"
{
restaurants(filters: { name: { endsWith: "Inc" } }) {
name
}
}
Simple examples for null checks operators (null, notNull)
# null - returns restaurants where description is null
{
restaurants(filters: { description: { null: true } }) {
name
}
}

# notNull - returns restaurants where description is not null
{
restaurants(filters: { description: { notNull: true } }) {
name
}
}
Simple examples for logical operators (and, or, not)
# and - both category must be "pizza" AND averagePrice must be < 20
{
restaurants(filters: {
and: [
{ category: { eq: "pizza" } },
{ averagePrice: { lt: 20 } }
]
}) {
name
}
}

# or - category is "pizza" OR category is "burger"
{
restaurants(filters: {
or: [
{ category: { eq: "pizza" } },
{ category: { eq: "burger" } }
]
}) {
name
}
}

# not - category must NOT be "pizza"
{
restaurants(filters: {
not: { category: { eq: "pizza" } }
}) {
name
}
}
Example with nested logical operators: use and, or, and not to find pizzerias under 20 euros
{
restaurants(
filters: {
and: [
{ not: { averagePrice: { gte: 20 } } }
{
or: [
{ name: { eq: "Pizzeria" } }
{ name: { startsWith: "Pizzeria" } }
]
}
]
}
) {
documentId
name
averagePrice
}
}
Deep filtering with the various APIs

有关如何使用各种 API 进行深度过滤的示例,请参阅 this blog article

排序

🌐 Sorting

查询可以接受带有以下语法的 sort 参数:

🌐 Queries can accept a sort parameter with the following syntax:

  • 根据单个值排序:sort: "value"
  • 根据多个值排序:sort: ["value1", "value2"]

排序顺序可以用 :asc(升序,默认,可省略)或 :desc(降序)来定义。

🌐 The sorting order can be defined with :asc (ascending order, default, can be omitted) or :desc (for descending order).

Example: Fetch and sort on name by ascending order
{
restaurants(sort: "name") {
documentId
name
}
}
Example: Fetch and sort on average price by descending order
{
restaurants(sort: "averagePrice:desc") {
documentId
name
averagePrice
}
}
Example: Fetch and sort on title by ascending order, then on average price by descending order
{
restaurants(sort: ["name:asc", "averagePrice:desc"]) {
documentId
name
averagePrice
}
}

分页

🌐 Pagination

Relay-style 查询可以接受一个pagination参数。结果可以通过页码或偏移量进行分页。

Note

分页方法不能混用。始终要么使用 pagepageSize,要么使用 startlimit

🌐 Pagination methods can not be mixed. Always use either page with pageSize or start with limit.

按页分页

🌐 Pagination by page

参数描述默认值
pagination.page页码1
pagination.pageSize每页条数10
Example query: Pagination by page
{
restaurants_connection(pagination: { page: 1, pageSize: 10 }) {
nodes {
documentId
name
}
pageInfo {
page
pageSize
pageCount
total
}
}
}

按偏移量分页

🌐 Pagination by offset

参数描述默认值最大值
pagination.start起始值0-
pagination.limit返回的实体数量10-1
Example query: Pagination by offset
{
restaurants_connection(pagination: { start: 10, limit: 19 }) {
nodes {
documentId
name
}
pageInfo {
page
pageSize
pageCount
total
}
}
}
Tip

pagination.limit 的默认值和最大值可以在 ./config/plugins.js 文件中通过 graphql.config.defaultLimitgraphql.config.maxLimit 键进行配置。

🌐 The default and maximum values for pagination.limit can be configured in the ./config/plugins.js file with the graphql.config.defaultLimit and graphql.config.maxLimit keys.

Many-to-many relation ordering with pagination

在使用分页查询多对多关系时,管理员面板中设置的自定义排序会被保留。如果在查询中对关系进行排序(例如,categories(sort: "name")),分页将遵循你指定的排序顺序,而不是内容管理器中配置的自定义排序。

🌐 When querying many-to-many relations with pagination, the custom order set in the admin panel is preserved. If you sort relations in a query (e.g., categories(sort: "name")), the pagination respects your specified sort order rather than the custom order configured in the content manager.

locale

[国际化 (i18n)](/cms/features/internationalization) 功能为 GraphQL API 添加了新功能:

🌐 The Internationalization (i18n) feature adds new features to the GraphQL API:

  • 在 GraphQL 模式中添加了 locale 字段。
  • GraphQL 可以用于:
    • 使用 locale 参数查询特定区域的文档
    • 用于针对特定语言环境的文档进行创建更新删除的变更

获取特定区域的所有文档

🌐 Fetch all documents in a specific locale

要获取特定区域的所有文档

A document in Strapi 5 is an API-only concept which represents all the variations of content (for different locales, for the draft and published versions) for a given entry found in the Content Manager.

More details can be found in the Documents introduction.

,请将 locale 参数传递给查询:

Example request
query {
restaurants(locale: "fr") {
documentId
name
locale
}
}
Example response
{
"data": {
"restaurants": [
{
"documentId": "a1b2c3d4e5d6f7g8h9i0jkl",
"name": "Restaurant Biscotte",
"locale": "fr"
},
{
"documentId": "m9n8o7p6q5r4s3t2u1v0wxyz",
"name": "Pizzeria Arrivederci",
"locale": "fr"
},
]
}
}

获取特定语言环境的文档

🌐 Fetch a document in a specific locale

要获取特定区域的文档

A document in Strapi 5 is an API-only concept which represents all the variations of content (for different locales, for the draft and published versions) for a given entry found in the Content Manager.

More details can be found in the Documents introduction.

,请将 documentIdlocale 参数传递给查询:

示例查询
query Restaurant($documentId: ID!, $locale: I18NLocaleCode) {
restaurant(documentId: "a1b2c3d4e5d6f7g8h9i0jkl", locale: "fr") {
documentId
name
description
locale
}
}
示例响应
{
"data": {
"restaurant": {
"documentId": "lviw819d5htwvga8s3kovdij",
"name": "Restaurant Biscotte",
"description": "Bienvenue au restaurant Biscotte!",
"locale": "fr"
}
}
}

创建一个新的本地化文档

🌐 Create a new localized document

locale 字段可以传递以创建针对特定语言环境的本地化文档

A document in Strapi 5 is an API-only concept which represents all the variations of content (for different locales, for the draft and published versions) for a given entry found in the Content Manager.

More details can be found in the Documents introduction.

(有关使用 GraphQL 进行变更的更多信息,请参阅 GraphQL API 文档)。

Example: Create a new restaurant for the French locale
mutation CreateRestaurant($data: RestaurantInput!, $locale: I18NLocaleCode) {
createRestaurant(
data: {
name: "Brasserie Bonjour",
description: "Description in French goes here"
},
locale: "fr"
) {
documentId
name
description
locale
}

为特定地区更新文档

🌐 Update a document for a specific locale

可以在变更中传入 locale 参数以更新给定语言环境的文档

A document in Strapi 5 is an API-only concept which represents all the variations of content (for different locales, for the draft and published versions) for a given entry found in the Content Manager.

More details can be found in the Documents introduction.

(有关使用 GraphQL 的变更的更多信息,请参阅 GraphQL API 文档)。

Example: Update the description field of restaurant for the French locale
mutation UpdateRestaurant($documentId: ID!, $data: RestaurantInput!, $locale: I18NLocaleCode) {
updateRestaurant(
documentId: "a1b2c3d4e5d6f7g8h9i0jkl"
data: {
description: "New description in French"
},
locale: "fr"
) {
documentId
name
description
locale
}

删除文档的语言区域

🌐 Delete a locale for a document

在变更中传递 locale 参数以删除文档的特定本地化

A document in Strapi 5 is an API-only concept which represents all the variations of content (for different locales, for the draft and published versions) for a given entry found in the Content Manager.

More details can be found in the Documents introduction.

mutation DeleteRestaurant($documentId: ID!, $locale: I18NLocaleCode) {
deleteRestaurant(documentId: "xzmzdo4k0z73t9i68a7yx2kk", locale: "fr") {
documentId
}
}

高级用例

🌐 Advanced use cases

点击以下卡片,查看利用 GraphQL API 和 Strapi 功能的更高级用例的简短指南:

🌐 Click on the following cards for short guides on more advanced use cases leveraging the GraphQL API and Strapi features:

Aggregations not yet available

GraphQL 聚合(count、avg、sum、min、max、groupBy)尚未在 @strapi/plugin-graphql 中实现。当该功能可用时,本节将会更新。

🌐 GraphQL aggregations (count, avg, sum, min, max, groupBy) are not yet implemented in @strapi/plugin-graphql. This section will be updated when the feature becomes available.

与此同时,你可以通过 REST API 获取文档总数(例如,GET /api/restaurants?pagination[pageSize]=1 返回 meta.pagination.total),或者编写一个使用 文档服务 API 来计算聚合的 自定义 GraphQL 解析器

🌐 In the meantime, you can get a total document count through the REST API (e.g., GET /api/restaurants?pagination[pageSize]=1 returns meta.pagination.total), or write a custom GraphQL resolver that uses the Document Service API to compute aggregations.