Skip to main content

🧠 了解 REST API 的 populate 参数

¥🧠 Understanding the populate parameter for the REST API

注意:示例响应可能与你的体验不同

此页面的内容可能尚未与 Strapi 5 完全同步:

¥The content of this page might not be fully up-to-date with Strapi 5 yet:

  • 所有概念信息和解释都是正确且最新的。

    ¥All the conceptual information and explanations are correct and up-to-date.

  • 但是,在示例中,响应内容可能略有不同。

    ¥However, in the examples, the response content might be slightly different.

Strapi 5.0.0(稳定版)发布后,以及 FoodAdvisor 示例应用升级到 Strapi 5 后,示例将完全更新。

¥Examples will be fully up-to-date after the Strapi 5.0.0 (stable version) release and as soon as the FoodAdvisor example application is upgraded to Strapi 5.

但是,响应示例略有不同不应妨碍你掌握本页所教授的基本概念。

¥However, having slightly different response examples should not prevent you from grasping the essential concepts taught in this page.

当使用 Strapi 的 REST API 查询内容类型时,默认情况下,响应仅包含顶层字段,不包含任何关系、媒体字段、组件或动态区域。

¥When querying content-types with Strapi's REST API, by default, responses only include top-level fields and do not include any relations, media fields, components, or dynamic zones.

在 Strapi REST API 上下文中填充意味着通过返回比默认返回的字段更多的字段,在响应中包含其他内容。你可以使用 populate 参数 来实现此目的。

¥Populating in the context of the Strapi REST API means including additional content with your response by returning more fields than the ones returned by default. You use the populate parameter to achieve this.

信息

在本指南中,示例是使用从 FoodAdvisor 示例应用附带的服务器查询的真实数据构建的。要自行测试示例,请设置 FoodAdvisor,在 /api/ 文件夹中启动服务器,并确保在发送查询之前为查询的内容类型授予适当的 find 权限。

¥Throughout this guide, examples are built with real data queried from the server included with the FoodAdvisor example application. To test examples by yourself, setup FoodAdvisor, start the server in the /api/ folder, and ensure that proper find permissions are given for the queried content-types before sending your queries.

本指南将详细解释以下用例:

¥The present guide will cover detailed explanations for the following use cases:

信息

填充几个深度级别通常称为 "深度填充"。

¥Populating several levels deep is often called "deep populate".

高级用例:填充创作者字段

除了在查询中使用 populate 参数的各种方式之外,你还可以构建自定义控制器作为填充创建者字段(例如 createdByupdatedBy)的解决方法。专门的 如何填充创建者字段 指南对此进行了解释。

¥In addition to the various ways of using the populate parameter in your queries, you can also build a custom controller as a workaround to populate creator fields (e.g., createdBy and updatedBy). This is explained in the dedicated How to populate creator fields guide.

填充所有关系和字段,深 1 层

¥Populate all relations and fields, 1 level deep

你可以通过单个查询返回所有关系、媒体字段、组件和动态区域。对于关系来说,这只适用于 1 层深度,以防止性能问题和较长的响应时间。

¥You can return all relations, media fields, components and dynamic zones with a single query. For relations, this will only work 1 level deep, to prevent performance issues and long response times.

要填充 1 级深度的所有内容,请将 populate=* 参数添加到你的查询中。

¥To populate everything 1 level deep, add the populate=* parameter to your query.

下图比较了 FoodAdvisor 示例应用在填充 1 层深度的所有内容和未填充所有内容的情况下返回的数据:

¥The following diagram compares data returned by the FoodAdvisor example application with and without populating everything 1 level deep:

Diagram with populate use cases with FoodAdvisor data

让我们比较并解释使用和不使用此查询参数时会发生什么:

¥Let's compare and explain what happens with and without this query parameter:

示例:没有 populate

¥Example: Without populate

如果没有 populate 参数,GET/api/articles 的请求仅返回默认属性,不会返回任何媒体字段、关系、组件或动态区域。

¥Without the populate parameter, a GET request to /api/articles only returns the default attributes and does not return any media fields, relations, components or dynamic zones.

以下示例是 articles 内容类型中所有 4 个条目的完整响应。

¥The following example is the full response for all 4 entries from the articles content-types.

请注意响应如何仅包含 titleslugcreatedAtupdatedAtpublishedAtlocale 字段,以及由 CKEditor 插件处理的文章的字段内容(ckeditor_content,为了简洁而被截断):

¥Notice how the response only includes the title, slug, createdAt, updatedAt, publishedAt, and locale fields, and the field content of the article as handled by the CKEditor plugin (ckeditor_content, truncated for brevity):

Example request

GET /api/articles

Example response
{
"data": [
{
"id": 1,
"documentId": "t3q2i3v1z2j7o8p6d0o4xxg",
"title": "Here's why you have to try basque cuisine, according to a basque chef",
"slug": "here-s-why-you-have-to-try-basque-cuisine-according-to-a-basque-chef",
"createdAt": "2021-11-09T13:33:19.948Z",
"updatedAt": "2023-06-02T10:57:19.584Z",
"publishedAt": "2022-09-22T09:30:00.208Z",
"locale": "en",
"ckeditor_content": // truncated content
},
{
"id": 2,
"documentId": "k2r5l0i9g3u2j3b4p7f0sed",
"title": "What are chinese hamburgers and why aren't you eating them?",
"slug": "what-are-chinese-hamburgers-and-why-aren-t-you-eating-them",
"createdAt": "2021-11-11T13:33:19.948Z",
"updatedAt": "2023-06-01T14:32:50.984Z",
"publishedAt": "2022-09-22T12:36:48.312Z",
"locale": "en",
"ckeditor_content": // truncated content
},
{
"id": 3,
"documentId": "k6m6l9q0n6v9z2m3i0z5jah"
"title": "7 Places worth visiting for the food alone",
"slug": "7-places-worth-visiting-for-the-food-alone",
"createdAt": "2021-11-12T13:33:19.948Z",
"updatedAt": "2023-06-02T11:30:00.075Z",
"publishedAt": "2023-06-02T11:30:00.075Z",
"locale": "en",
"ckeditor_content": // truncated content
},
{
"id": 4,
"documentId": "d5m4b6z6g5d9e3v1k9n5gbn",
"title": "If you don't finish your plate in these countries, you might offend someone",
"slug": "if-you-don-t-finish-your-plate-in-these-countries-you-might-offend-someone",
"createdAt": "2021-11-15T13:33:19.948Z",
"updatedAt": "2023-06-02T10:59:35.148Z",
"publishedAt": "2022-09-22T12:35:53.899Z",
"locale": "en",
"ckeditor_content": // truncated content
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 4
}
}
}

示例:与 populate=*

¥Example: With populate=*

使用 populate=* 参数,对 /api/articlesGET 请求也会返回所有媒体字段、第一级关系、组件和动态区域。

¥With the populate=* parameter, a GET request to /api/articles also returns all media fields, first-level relations, components and dynamic zones.

以下示例是 articles 内容类型中所有 4 个条目中第一个条目的完整响应(为简洁起见,ID 为 2、3 和 4 的文章中的数据被截断)。

¥The following example is the full response for the first of all 4 entries from the articles content-types (the data from articles with ids 2, 3, and 4 is truncated for brevity).

向下滚动可以看到响应大小比没有填充时大得多。响应现在包含其他字段(请参阅高亮的行),例如:

¥Scroll down to see that the response size is much bigger than without populate. The response now includes additional fields (see highlighted lines) such as:

  • image 媒体字段(存储有关文章封面的所有信息,包括所有不同的格式),

    ¥the image media field (which stores all information about the article cover, including all its different formats),

  • blocks 动态区域和 seo 组件的第一级字段,

    ¥the first-level fields of the blocks dynamic zone and the seo component,

  • category 关系及其字段,

    ¥the category relation and its fields,

  • 甚至还有一些有关其他语言翻译的文章的信息,如 localizations 对象所示。

    ¥and even some information about the articles translated in other languages, as shown by the localizations object.

提示

要填充深层嵌套组件,请参阅 填充组件 部分。

¥To populate deeply nested components, see the populate components section.


Example request

GET /api/articles?populate=*

Example response
{
"data": [
{
"id": 1,
"title": "Here's why you have to try basque cuisine, according to a basque chef",
"slug": "here-s-why-you-have-to-try-basque-cuisine-according-to-a-basque-chef",
"createdAt": "2021-11-09T13:33:19.948Z",
"updatedAt": "2023-06-02T10:57:19.584Z",
"publishedAt": "2022-09-22T09:30:00.208Z",
"locale": "en",
"ckeditor_content": // truncated content
"image": {
"data": {
"id": 12,
"documentId": "o5d4b0l4p8l4o4k5n1l3rxa",
"name": "Basque dish",
"alternativeText": "Basque dish",
"caption": "Basque dish",
"width": 758,
"height": 506,
"formats": {
"thumbnail": {
"name": "thumbnail_https://4d40-2a01-cb00-c8b-1800-7cbb-7da-ea9d-2011.ngrok.io/uploads/basque_cuisine_17fa4567e0.jpeg",
"hash": "thumbnail_basque_cuisine_17fa4567e0_f033424240",
"ext": ".jpeg",
"mime": "image/jpeg",
"width": 234,
"height": 156,
"size": 11.31,
"path": null,
"url": "/uploads/thumbnail_basque_cuisine_17fa4567e0_f033424240.jpeg"
},
"medium": {
"name": "medium_https://4d40-2a01-cb00-c8b-1800-7cbb-7da-ea9d-2011.ngrok.io/uploads/basque_cuisine_17fa4567e0.jpeg",
"hash": "medium_basque_cuisine_17fa4567e0_f033424240",
"ext": ".jpeg",
"mime": "image/jpeg",
"width": 750,
"height": 501,
"size": 82.09,
"path": null,
"url": "/uploads/medium_basque_cuisine_17fa4567e0_f033424240.jpeg"
},
"small": {
"name": "small_https://4d40-2a01-cb00-c8b-1800-7cbb-7da-ea9d-2011.ngrok.io/uploads/basque_cuisine_17fa4567e0.jpeg",
"hash": "small_basque_cuisine_17fa4567e0_f033424240",
"ext": ".jpeg",
"mime": "image/jpeg",
"width": 500,
"height": 334,
"size": 41.03,
"path": null,
"url": "/uploads/small_basque_cuisine_17fa4567e0_f033424240.jpeg"
}
},
"hash": "basque_cuisine_17fa4567e0_f033424240",
"ext": ".jpeg",
"mime": "image/jpeg",
"size": 58.209999999999994,
"url": "/uploads/basque_cuisine_17fa4567e0_f033424240.jpeg",
"previewUrl": null,
"provider": "local",
"provider_metadata": null,
"createdAt": "2021-11-23T14:05:33.460Z",
"updatedAt": "2021-11-23T14:05:46.084Z"
}
}
},
"blocks": [
{
"id": 2,
"__component": "blocks.related-articles"
},
{
"id": 2,
"documentId": "w8r5k8o8v0t9l9e0d7y6vco",
"__component": "blocks.cta-command-line",
"theme": "primary",
"title": "Want to give a try to a Strapi starter?",
"text": "❤️",
"commandLine": "git clone https://github.com/strapi/nextjs-corporate-starter.git"
}
],
"seo": {
"id": 1,
"documentId": "h7c8d0u3i3q5v1j3j3r4cxf",
"metaTitle": "Articles - FoodAdvisor",
"metaDescription": "Discover our articles about food, restaurants, bars and more! - FoodAdvisor",
"keywords": "food",
"metaRobots": null,
"structuredData": null,
"metaViewport": null,
"canonicalURL": null
},
"category": {
"data": {
"id": 4,
"documentId": "t1t3d9k6n1k5a6r8l7f8rox",
"name": "European",
"slug": "european",
"createdAt": "2021-11-09T13:33:20.123Z",
"updatedAt": "2021-11-09T13:33:20.123Z"
}
},
"localizations": {
"data": [
{
"id": 10,
"documentId": "h7c8d0u3i3q5v1j3j3r4cxf",
"title": "Voici pourquoi il faut essayer la cuisine basque, selon un chef basque",
"slug": "voici-pourquoi-il-faut-essayer-la-cuisine-basque-selon-un-chef-basque",
"createdAt": "2021-11-18T13:33:19.948Z",
"updatedAt": "2023-06-02T10:57:19.606Z",
"publishedAt": "2022-09-22T13:00:00.069Z",
"locale": "fr-FR",
"ckeditor_content": // truncated content
}
]
}
}
},
{
"id": 2,
// truncated content
},
{
"id": 3,
// truncated content
},
{
"id": 4,
// truncated content
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 4
}
}
}

填充特定关系和字段

¥Populate specific relations and fields

你还可以通过显式定义要填充的内容来填充特定的关系和字段。这要求你知道要填充的字段和关系的名称。

¥You can also populate specific relations and fields, by explicitly defining what to populate. This requires that you know the name of fields and relations to populate.

以这种方式填充的关系和字段可以是 1 级或几级深。下图比较了填充 1 层深2 层深FoodAdvisor 示例应用返回的数据:

¥Relations and fields populated this way can be 1 or several levels deep. The following diagram compares data returned by the FoodAdvisor example application when you populate 1 level deep vs. 2 levels deep:

Diagram with populate use cases with FoodAdvisor data

🤓 Different populating strategies for similar results

Depending on your data structure, you might get similar data presented in different ways with different queries. For instance, the FoodAdvisor example application includes the article, category, and restaurant content-types that are all in relation to each other in different ways. This means that if you want to get data about the 3 content-types in a single GET request, you have 2 options:

  • 查询文章并填充类别,并填充类别和餐厅之间的嵌套关系(2 级深度人口

    ¥query articles and populate categories, plus populate the nested relation between categories and restaurants (2 levels deep population)

  • 查询类别并填充文章和餐厅,因为类别与其他 2 个内容类型 (1 层深) 具有第一级关系

    ¥query categories and populate both articles and restaurants because categories have a 1st level relation with the 2 other content-types (1 level deep)

下图说明了这两种不同的策略:

¥The 2 different strategies are illustrated in the following diagram:

Diagram with populate use cases with FoodAdvisor data

Populate as an object vs. populate as an array: Using the interactive query builder

手动构建高级查询参数的语法可能非常复杂。我们建议你使用我们的 交互式查询构建器 工具来生成 URL。

¥The syntax for advanced query parameters can be quite complex to build manually. We recommend you use our interactive query builder tool to generate the URL.

使用此工具,你将以熟悉的 (JavaScript) 格式编写干净且可读的请求,这将帮助你了解不同查询和不同填充方式之间的差异。例如,填充 2 层深度意味着使用 populate 作为对象,而填充多个关系 1 层深度意味着使用 populate 作为数组:

¥Using this tool, you will write clean and readable requests in a familiar (JavaScript) format, which should help you understand the differences between different queries and different ways of populating. For instance, populating 2 levels deep implies using populate as an object, while populating several relations 1 level deep implies using populate as an array:

填充为对象
(填充 1 个关系多个级别):

¥Populate as an object
(to populate 1 relation several levels deep):

{
populate: {
category: {
populate: ['restaurants'],
},
},
}

填充为数组
(填充许多 1 层深的关系)

¥Populate as an array
(to populate many relations 1 level deep)

{
populate: [
'articles',
'restaurants'
],
}

为特定关系填充 1 层深度

¥Populate 1 level deep for specific relations

你可以使用 populate 参数作为数组来填充 1 层深度的特定关系。

¥You can populate specific relations 1 level deep by using the populate parameter as an array.

由于 REST API 使用 LHS 括号表示法(即带有方括号 []),因此填充 1 层深度的参数语法如下所示:

¥Since the REST API uses the LHS bracket notation (i.e., with square brackets []), the parameter syntaxes to populate 1 level deep would look like the following:

要填充多少个关系语法示例
只有 1 个关系populate[0]=a-relation-name
几个关系populate[0]=relation-name&populate[1]=another-relation-name&populate[2]=yet-another-relation-name

让我们比较并解释向 FoodAdvisor 示例应用发送查询时,填充和不填充 1 层深度的关系会发生什么:

¥Let's compare and explain what happens with and without populating relations 1 level deep when sending queries to the FoodAdvisor example application:

示例:没有 populate

¥Example: Without populate

如果没有 populate 参数,GET/api/articles 请求仅返回默认属性。

¥Without the populate parameter, a GET request to /api/articles only returns the default attributes.

以下示例是 articles 内容类型中所有 4 个条目的完整响应。

¥The following example is the full response for all 4 entries from the articles content-type.

请注意,响应不包含任何媒体字段、关系、组件或动态区域:

¥Notice that the response does not include any media fields, relations, components or dynamic zones:


Example request

GET /api/articles

Example response
{
"data": [
{
"id": 1,
"documentId": "x2m0d7d9o4m2z3u2r2l9yes",
"title": "Here's why you have to try basque cuisine, according to a basque chef",
"slug": "here-s-why-you-have-to-try-basque-cuisine-according-to-a-basque-chef",
"createdAt": "2021-11-09T13:33:19.948Z",
"updatedAt": "2023-06-02T10:57:19.584Z",
"publishedAt": "2022-09-22T09:30:00.208Z",
"locale": "en",
"ckeditor_content": "…", // truncated content
},
{
"id": 2,
"documentId": "k6m6l9q0n6v9z2m3i0z5jah",
"title": "What are chinese hamburgers and why aren't you eating them?",
"slug": "what-are-chinese-hamburgers-and-why-aren-t-you-eating-them",
"createdAt": "2021-11-11T13:33:19.948Z",
"updatedAt": "2023-06-01T14:32:50.984Z",
"publishedAt": "2022-09-22T12:36:48.312Z",
"locale": "en",
"ckeditor_content": "…", // truncated content
},
{
"id": 3,
"documentId": "o5d4b0l4p8l4o4k5n1l3rxa",
"title": "7 Places worth visiting for the food alone",
"slug": "7-places-worth-visiting-for-the-food-alone",
"createdAt": "2021-11-12T13:33:19.948Z",
"updatedAt": "2023-06-02T11:30:00.075Z",
"publishedAt": "2023-06-02T11:30:00.075Z",
"locale": "en",
"ckeditor_content": "…", // truncated content
},
{
"id": 4,
"documentId": "t3q2i3v1z2j7o8p6d0o4xxg",
"title": "If you don't finish your plate in these countries, you might offend someone",
"slug": "if-you-don-t-finish-your-plate-in-these-countries-you-might-offend-someone",
"createdAt": "2021-11-15T13:33:19.948Z",
"updatedAt": "2023-06-02T10:59:35.148Z",
"publishedAt": "2022-09-22T12:35:53.899Z",
"locale": "en",
"ckeditor_content": "…", // truncated content
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 4
}
}
}
}

示例:与 populate[0]=category

¥Example: With populate[0]=category

populate[0]=category 添加到请求后,我们明确要求包含有关 category 的一些信息,category 是链接 articlescategories 内容类型的关系字段。

¥With populate[0]=category added to the request, we explicitly ask to include some information about category, which is a relation field that links the articles and the categories content-types.

以下示例是 articles 内容类型中所有 4 个条目的完整响应。

¥The following example is the full response for all 4 entries from the articles content-type.

请注意,响应现在包含每篇文章的 category 字段的附加数据(请参阅高亮的行):

¥Notice that the response now includes additional data with the category field for each article (see highlighted lines):

Example request

GET /api/articles?populate[0]=category

Example response
{
"data": [
{
"id": 1,
"documentId": "w8r5k8o8v0t9l9e0d7y6vco",
"title": "Here's why you have to try basque cuisine, according to a basque chef",
"slug": "here-s-why-you-have-to-try-basque-cuisine-according-to-a-basque-chef",
"createdAt": "2021-11-09T13:33:19.948Z",
"updatedAt": "2023-06-02T10:57:19.584Z",
"publishedAt": "2022-09-22T09:30:00.208Z",
"locale": "en",
"ckeditor_content": "…", // truncated content
"category": {
"data": {
"id": 4,
"documentId": "u6x8u7o7j5q1l5y3t8j9yxi",
"name": "European",
"slug": "european",
"createdAt": "2021-11-09T13:33:20.123Z",
"updatedAt": "2021-11-09T13:33:20.123Z"
}
}
},
{
"id": 2,
"documentId": "k6m6l9q0n6v9z2m3i0z5jah",
"title": "What are chinese hamburgers and why aren't you eating them?",
"slug": "what-are-chinese-hamburgers-and-why-aren-t-you-eating-them",
"createdAt": "2021-11-11T13:33:19.948Z",
"updatedAt": "2023-06-01T14:32:50.984Z",
"publishedAt": "2022-09-22T12:36:48.312Z",
"locale": "en",
"ckeditor_content": "…", // truncated content
"category": {
"data": {
"id": 13,
"documentId": "x2m0d7d9o4m2z3u2r2l9yes",
"name": "Chinese",
"slug": "chinese",
"createdAt": "2021-11-09T13:33:20.123Z",
"updatedAt": "2021-11-09T13:33:20.123Z"
}
}
},
{
"id": 3,
"title": "7 Places worth visiting for the food alone",
"slug": "7-places-worth-visiting-for-the-food-alone",
"createdAt": "2021-11-12T13:33:19.948Z",
"updatedAt": "2023-06-02T11:30:00.075Z",
"publishedAt": "2023-06-02T11:30:00.075Z",
"locale": "en",
"ckeditor_content": "…", // truncated content
"category": {
"data": {
"id": 3,
"documentId": "h7c8d0u3i3q5v1j3j3r4cxf",
"name": "International",
"slug": "international",
"createdAt": "2021-11-09T13:33:20.123Z",
"updatedAt": "2021-11-09T13:33:20.123Z"
}
}
},
{
"id": 4,
"documentId": "t1t3d9k6n1k5a6r8l7f8rox",
"title": "If you don't finish your plate in these countries, you might offend someone",
"slug": "if-you-don-t-finish-your-plate-in-these-countries-you-might-offend-someone",
"createdAt": "2021-11-15T13:33:19.948Z",
"updatedAt": "2023-06-02T10:59:35.148Z",
"publishedAt": "2022-09-22T12:35:53.899Z",
"locale": "en",
"ckeditor_content": "…", // truncated content
"category": {
"data": {
"id": 3,
"documentId": "u6x8u7o7j5q1l5y3t8j9yxi",
"name": "International",
"slug": "international",
"createdAt": "2021-11-09T13:33:20.123Z",
"updatedAt": "2021-11-09T13:33:20.123Z"
}
}
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 4
}
}
}

为特定关系填充多个深度级别

¥Populate several levels deep for specific relations

你还可以填充多个深度级别的特定关系。例如,当你填充一个关系,而该关系本身又填充另一个关系时,你将填充 2 层深度。本指南中介绍的示例是填充 2 层深度。

¥You can also populate specific relations several levels deep. For instance, when you populate a relation which itself populates another relation, you are populating 2 levels deep. Populating 2 levels deep is the example covered in this guide.

提醒

可以填充的级别数量没有限制。但是,填充的深度越深,执行请求所需的时间就越长。

¥There is no limit on the number of levels that can be populated. However, the deeper the populates, the more the request will take time to be performed.

由于 REST API 使用 LHS 括号表示法(即带有方括号 []),例如,如果你想要填充嵌套在另一个关系中的关系,则参数语法将如下所示:

¥Since the REST API uses the LHS bracket notation, (i.e., with square brackets []), for instance if you want to populate a relation nested inside another relation, the parameter syntax would look like the following:

populate[first-level-relation-to-populate][populate][0]=second-level-relation-to-populate

提示

手动构建高级查询参数的语法可能非常复杂。我们建议你使用我们的 交互式查询构建器 工具来生成 URL。例如,以下示例中使用的 /api/articles?populate[category][populate][0]=restaurants URL 是通过使用我们的工具转换以下对象生成的:

¥The syntax for advanced query parameters can be quite complex to build manually. We recommend you use our interactive query builder tool to generate the URL. For instance, the /api/articles?populate[category][populate][0]=restaurants URL used in the following examples has been generated by converting the following object using our tool:

{
populate: {
category: {
populate: ['restaurants'],
},
},
}

FoodAdvisor 示例应用包括内容类型之间的各种级别的关系。例如:

¥The FoodAdvisor example application includes various levels of relations between content-types. For instance:

  • article 内容类型包括与 category 内容类型的关系,

    ¥an article content-type includes a relation with the category content-type,

  • category 也可以分配给任何 restaurant 内容类型。

    ¥but a category can also be assigned to any restaurant content-type.

通过对 /api/articles 的单个 GET 请求和适当的填充参数,你可以同时返回有关文章、餐馆和类别的信息。

¥With a single GET request to /api/articles and the appropriate populate parameters, you can return information about articles, restaurants, and categories simultaneously.

让我们比较并解释向 FoodAdvisor 发送查询时使用 populate[0]=category(1 级深)和 populate[category][populate][0]=restaurants(2 级深)返回的响应:

¥Let's compare and explain the responses returned with populate[0]=category (1 level deep) and populate[category][populate][0]=restaurants (2 levels deep) when sending queries to FoodAdvisor:

示例:具有 1 级深度人口

¥Example: With 1-level deep population

当我们仅填充 1 层深度时,询问与文章关联的类别,我们可以获得以下示例响应(高亮的行显示 category 关系字段):

¥When we only populate 1 level deep, asking for the categories associated to articles, we can get the following example response (highlighted lines show the category relations field):

Example request

GET /api/articles?populate[0]=category

Example response
{
"data": [
{
"id": 1,
"documentId": "9ih6hy1bnma3q3066kdwt3",
"title": "Here's why you have to try basque cuisine, according to a basque chef",
"slug": "here-s-why-you-have-to-try-basque-cuisine-according-to-a-basque-chef",
"createdAt": "2021-11-09T13:33:19.948Z",
"updatedAt": "2023-06-02T10:57:19.584Z",
"publishedAt": "2022-09-22T09:30:00.208Z",
"locale": "en",
"ckeditor_content": "…", // truncated content
"category": {
"data": {
"id": 4,
"name": "European",
"slug": "european",
"createdAt": "2021-11-09T13:33:20.123Z",
"updatedAt": "2021-11-09T13:33:20.123Z"
}
}
},
{
"id": 2,
"documentId": "sen6qfgxcac13pwchf8xbu",
"title": "What are chinese hamburgers and why aren't you eating them?",
"slug": "what-are-chinese-hamburgers-and-why-aren-t-you-eating-them",
"createdAt": "2021-11-11T13:33:19.948Z",
"updatedAt": "2023-06-01T14:32:50.984Z",
"publishedAt": "2022-09-22T12:36:48.312Z",
"locale": "en",
"ckeditor_content": "…", // truncated content
"category": {
"data": {
"id": 13,
"documentId": "r3rhzcxd7gjx07vkq3pia5",
"name": "Chinese",
"slug": "chinese",
"createdAt": "2021-11-09T13:33:20.123Z",
"updatedAt": "2021-11-09T13:33:20.123Z"
}
}
},
{
"id": 3,
"documentId": "s9uu7rkukhfcsmj2e60b67",
"title": "7 Places worth visiting for the food alone",
"slug": "7-places-worth-visiting-for-the-food-alone",
"createdAt": "2021-11-12T13:33:19.948Z",
"updatedAt": "2023-06-02T11:30:00.075Z",
"publishedAt": "2023-06-02T11:30:00.075Z",
"locale": "en",
"ckeditor_content": "…", // truncated content
"category": {
"data": {
"id": 3,
"documentId": "4sevz15w6bdol6y4t8kblk",
"name": "International",
"slug": "international",
"createdAt": "2021-11-09T13:33:20.123Z",
"updatedAt": "2021-11-09T13:33:20.123Z"
}
}
},
{
"id": 4,
"documentId": "iy5ifm3xj8q0t8vlq6l23h",
"title": "If you don't finish your plate in these countries, you might offend someone",
"slug": "if-you-don-t-finish-your-plate-in-these-countries-you-might-offend-someone",
"createdAt": "2021-11-15T13:33:19.948Z",
"updatedAt": "2023-06-02T10:59:35.148Z",
"publishedAt": "2022-09-22T12:35:53.899Z",
"locale": "en",
"ckeditor_content": "…", // truncated content
"category": {
"data": {
"id": 3,
"documentId": "0eor603u8qej933maphdv3",
"name": "International",
"slug": "international",
"createdAt": "2021-11-09T13:33:20.123Z",
"updatedAt": "2021-11-09T13:33:20.123Z"
}
}
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 4
}
}
}

示例:具有 2 级深度人口

¥Example: With 2-level deep population

当我们填充 2 层深度时,询问与文章相关的类别,以及与这些类别相关的餐馆,我们可以得到以下示例响应。

¥When we populate 2 levels deep, asking for the categories associated to articles, but also for restaurants associated to these categories, we can get the following example response.

请注意,我们现在将 restaurants 关系字段包含在 category 关系内的响应中(请参见高亮的行):

¥Notice that we now have the restaurants relation field included with the response inside the category relation (see highlighted lines):

Example request

GET /api/articles?populate[category][populate][0]=restaurants

Example response
{{
"data": [
{
"id": 1,
"documentId": "iy5ifm3xj8q0t8vlq6l23h",
"attributes": {
"title": "Here's why you have to try basque cuisine, according to a basque chef",
"slug": "here-s-why-you-have-to-try-basque-cuisine-according-to-a-basque-chef",
"createdAt": "2021-11-09T13:33:19.948Z",
"updatedAt": "2023-06-02T10:57:19.584Z",
"publishedAt": "2022-09-22T09:30:00.208Z",
"locale": "en",
"ckeditor_content": "…", // truncated content
"category": {
"data": {
"id": 4,
"name": "European",
"slug": "european",
"createdAt": "2021-11-09T13:33:20.123Z",
"updatedAt": "2021-11-09T13:33:20.123Z",
"restaurants": {
"data": [
{
"id": 1,
"documentId": "ozlqrdxpnjb7wtvf6lp74v",
"name": "Mint Lounge",
"slug": "mint-lounge",
"price": "p3",
"createdAt": "2021-11-09T14:07:47.125Z",
"updatedAt": "2021-11-23T16:41:30.504Z",
"publishedAt": "2021-11-23T16:41:30.501Z",
"locale": "en"
},
{
"id": 9,
// truncated content
},
{
"id": 10,
// truncated content
},
{
"id": 12,
// truncated content
},
{
"id": 21,
// truncated content
},
{
"id": 26,
// truncated content
}
]
}
}
}
}
},
{
"id": 2,
// truncated content
},
{
"id": 3,
// truncated content
},
{
"id": 4,
// truncated content
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 4
}
}
}

填充组件

¥Populate components

默认情况下,组件和动态区域不包含在响应中,你需要显式填充每个动态区域、组件及其嵌套组件。

¥Components and dynamic zones are not included in responses by default and you need to explicitly populate each dynamic zones, components, and their nested components.

由于 REST API 使用 LHS 括号表示法(即带有方括号 []),因此你需要传递 populate 数组中的所有元素。还可以传递嵌套字段,参数语法如下所示:

¥Since the REST API uses the LHS bracket notation, (i.e., with square brackets []), you need to pass all elements in a populate array. Nested fields can also be passed, and the parameter syntax could look like the following:

populate[0]=a-first-field&populate[1]=a-second-field&populate[2]=a-third-field&populate[3]=a-third-field.a-nested-field&populate[4]=a-third-field.a-nested-component.a-nested-field-within-the-component

提示

手动构建高级查询参数的语法可能非常复杂。我们建议你使用我们的 交互式查询构建器 工具来生成 URL。例如,以下示例中使用的 /api/articles?populate[0]=seo&populate[1]=seo.metaSocial&populate[2]=seo.metaSocial.image URL 是通过使用我们的工具转换以下对象生成的:

¥The syntax for advanced query parameters can be quite complex to build manually. We recommend you use our interactive query builder tool to generate the URL. For instance, the /api/articles?populate[0]=seo&populate[1]=seo.metaSocial&populate[2]=seo.metaSocial.image URL used in the following examples has been generated by converting the following object using our tool:

{
populate: [
'seoData',
'seoData.sharedImage',
'seoData.sharedImage.media',
],
},

FoodAdvisor 示例应用包含各种组件,甚至包含嵌套在其他组件内的组件。例如:

¥The FoodAdvisor example application includes various components and even components nested inside other components. For instance:

  • article 内容类型包括 seo 组件 1,

    ¥an article content-type includes a seo component 1,

  • seo 组件包含嵌套的可重复 metaSocial 组件 2,

    ¥the seo component includes a nested, repeatable metaSocial component 2,

  • 并且 metaSocial 组件本身有多个字段,包括 image 媒体字段 3

    ¥and the metaSocial component itself has several fields, including an image media field 3.

FoodAdvisor's SEO component structure in the Content-Type Builder

默认情况下,GET 请求对 /api/articles 的响应中不包含这些字段或组件。但通过适当的填充参数,你可以在单个请求中返回所有这些参数。

¥By default, none of these fields or components are included in the response of a GET request to /api/articles. But with the appropriate populate parameters, you can return all of them in a single request.

让我们比较并解释 populate[0]=seo(第一级组件)和 populate[0]=seo&populate[1]=seo.metaSocial(嵌套在第一级组件内的第二级组件)返回的响应:

¥Let's compare and explain the responses returned with populate[0]=seo (1st level component) and populate[0]=seo&populate[1]=seo.metaSocial (2nd level component nested within the 1st level component):

示例:仅第一级组件

¥Example: Only 1st level component

当我们只填充 seo 组件时,我们只深入 1 层,我们可以获得以下示例响应。高亮的线显示 seo 组件。

¥When we only populate the seo component, we go only 1 level deep, and we can get the following example response. Highlighted lines show the seo component.

请注意,没有提及嵌套在 seo 组件中的 metaSocial 组件:

¥Notice there's no mention of the metaSocial component nested within the seo component:

Example request

GET /api/articles?populate[0]=seo

Example response
{
"data": [
{
"id": 1,
"documentId": "md60m5cy3dula5g87x1uar",
"title": "Here's why you have to try basque cuisine, according to a basque chef",
"slug": "here-s-why-you-have-to-try-basque-cuisine-according-to-a-basque-chef",
"createdAt": "2021-11-09T13:33:19.948Z",
"updatedAt": "2023-06-02T10:57:19.584Z",
"publishedAt": "2022-09-22T09:30:00.208Z",
"locale": "en",
"ckeditor_content": "…", // truncated content
"seo": {
"id": 1,
"documentId": "kqcwhq6hes25kt9ebj8x7j",
"metaTitle": "Articles - FoodAdvisor",
"metaDescription": "Discover our articles about food, restaurants, bars and more! - FoodAdvisor",
"keywords": "food",
"metaRobots": null,
"structuredData": null,
"metaViewport": null,
"canonicalURL": null
}
},
{
"id": 2,
// truncated content
},
{
"id": 3,
// truncated content
},
{
"id": 4,
// truncated content
},
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 4
}
}
}

示例:第一级和第二级组件

¥Example: 1st level and 2nd level component

当我们填充 2 层深度时,询问嵌套在 seo 中的 seo 组件和 metaSocial 组件,我们可以获得以下示例响应。

¥When we populate 2 levels deep, asking both for the seo component and the metaSocial component nested inside seo, we can get the following example response.

请注意,我们现在在响应中包含了 metaSocial 组件相关数据(请参见高亮的行):

¥Notice that we now have the metaSocial component-related data included with the response (see highlighted lines):

Example request

GET /api/articles?populate[0]=seo&populate[1]=seo.metaSocial

Example response
{
"data": [
{
"id": 1,
"documentId": "c2imt19iywk27hl2ftph7s",
"title": "Here's why you have to try basque cuisine, according to a basque chef",
"slug": "here-s-why-you-have-to-try-basque-cuisine-according-to-a-basque-chef",
"createdAt": "2021-11-09T13:33:19.948Z",
"updatedAt": "2023-06-02T10:57:19.584Z",
"publishedAt": "2022-09-22T09:30:00.208Z",
"locale": "en",
"ckeditor_content": "…", // truncated content
"seo": {
"id": 1,
"documentId": "e8cnux5ejxyqrejd5addfv",
"metaTitle": "Articles - FoodAdvisor",
"metaDescription": "Discover our articles about food, restaurants, bars and more! - FoodAdvisor",
"keywords": "food",
"metaRobots": null,
"structuredData": null,
"metaViewport": null,
"canonicalURL": null,
"metaSocial": [
{
"id": 1,
"documentId": "ks7xsp9fewoi0qljcz9qa0",
"socialNetwork": "Facebook",
"title": "Browse our best articles about food and restaurants ",
"description": "Discover our articles about food, restaurants, bars and more!"
}
]
}
},
{
"id": 2,
// truncated content
},
{
"id": 3,
// truncated content
},
{
"id": 4,
// truncated content
},
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 4
}
}
}

填充动态区域

¥Populate dynamic zones

动态区域本质上是高度动态的内容结构。要填充动态区域及其内容,需要明确定义要用响应填充的内容。

¥Dynamic zones are highly dynamic content structures by essence. To populate dynamic zones and their content, you need to explicitly define what to populate with the response.

为此,你可以使用 on 属性定义每个组件的填充查询。

¥To do so, you can define per-component populate queries using the on property.

例如,在 FoodAdvisor 示例应用中:

¥For instance, in the FoodAdvisor example application:

  • blocks 动态区域存在于 article 内容类型 1

    ¥A blocks dynamic zone exists the article content-type 1.

  • 动态区域包括 3 个不同的组件:relatedArticles 2faq 3,和 CtaCommandLine 4。所有组件都有包含各种字段的不同数据结构。

    ¥The dynamic zone includes 3 different components: relatedArticles 2, faq 3, and CtaCommandLine 4. All components have a different data structure containing various fields.

  • relatedArticles 组件与文章内容类型具有 articles 关系 5

    ¥The relatedArticles component has an articles relation 5 with the article content-type.

FoodAdvisor's 'blocks' dynamic zone structure in the Content-Type Builder

默认情况下,GET 请求对 /api/articles 的响应中不包含任何深层嵌套字段或关系。通过适当的填充参数并应用详细的填充策略,你可以精确地返回所需的数据。

¥By default, none of the deeply nested fields or relations are included in the response of a GET request to /api/articles. With the appropriate populate parameters and by applying a detailed population strategy, you can return precisely the data you need.

提示

手动构建高级查询参数的语法可能非常复杂。我们建议你使用我们的 交互式查询构建器 工具来生成 URL。例如,以下示例中使用的 /api/articles?populate[blocks][on][blocks.related-articles][populate][articles][populate][0]=image&populate[blocks][on][blocks.cta-command-line][populate]=* URL 是通过使用我们的工具转换以下对象生成的:

¥The syntax for advanced query parameters can be quite complex to build manually. We recommend you use our interactive query builder tool to generate the URL. For instance, the /api/articles?populate[blocks][on][blocks.related-articles][populate][articles][populate][0]=image&populate[blocks][on][blocks.cta-command-line][populate]=* URL used in the following example has been generated by converting the following object using our tool:

{
populate: {
blocks: { // asking to populate the blocks dynamic zone
on: { // using a detailed population strategy to explicitly define what you want
'blocks.related-articles': {
populate: {
'articles': {
populate: ['image']
}
}
},
'blocks.cta-command-line': {
populate: '*'
}
},
},
},
}

让我们通过共享人口策略和详细人口策略的一些示例来比较和解释返回的响应:

¥Let's compare and explain the responses returned with some examples of a shared population strategy and a detailed population strategy:

示例

¥Example

当我们填充 blocks 动态区域时,我们明确定义要填充哪些数据。

¥When we populate the blocks dynamic zone, we explicitly define which data to populate.

在以下示例响应中,高亮的行显示:

¥In the following example response, highlighted lines show that:

  • 我们深入填充了 relatedArticles 组件的 articles 关系,甚至是相关文章的 image 媒体字段。

    ¥We deeply populate the articles relation of the relatedArticles component, and even the image media field of the related article.

  • 但由于我们只要求填充 CtaCommandLine 组件的所有内容,而没有为 faq 组件定义任何内容,因此不会返回 faq 组件的任何数据。

    ¥But because we have only asked to populate everything for the CtaCommandLine component and have not defined anything for the faq component, no data from the faq component is returned.

Example request with a detailed population

GET /api/articles?populate[blocks][on][blocks.related-articles][populate][articles][populate][0]=image&populate[blocks][on][blocks.cta-command-line][populate]=*

Example response with a detailed population
{
"data": [
{
"id": 1,
"documentId": "it9bbhcgc6mcfsqas7h1dp",
"title": "Here's why you have to try basque cuisine, according to a basque chef",
"slug": "here-s-why-you-have-to-try-basque-cuisine-according-to-a-basque-chef",
"createdAt": "2021-11-09T13:33:19.948Z",
"updatedAt": "2023-06-02T10:57:19.584Z",
"publishedAt": "2022-09-22T09:30:00.208Z",
"locale": "en",
"ckeditor_content": "…", // truncated content
"blocks": [
{
"id": 2,
"documentId": "e8cnux5ejxyqrejd5addfv",
"__component": "blocks.related-articles",
"articles": {
"data": [
{
"id": 2,
"documentId": "wkgojrcg5bkz8teqx1foz7",
"title": "What are chinese hamburgers and why aren't you eating them?",
"slug": "what-are-chinese-hamburgers-and-why-aren-t-you-eating-them",
"createdAt": "2021-11-11T13:33:19.948Z",
"updatedAt": "2023-06-01T14:32:50.984Z",
"publishedAt": "2022-09-22T12:36:48.312Z",
"locale": "en",
"ckeditor_content": "…", // truncated content
"image": {
"data": {
// …
}
}
}
},
{
"id": 3,
// …
},
{
"id": 4,
// …
}
]
}
},
{
"id": 2,
"__component": "blocks.cta-command-line",
"theme": "primary",
"title": "Want to give a try to a Strapi starter?",
"text": "❤️",
"commandLine": "git clone https://github.com/strapi/nextjs-corporate-starter.git"
}
]
},
{
"id": 2,
// …
},
{
"id": 3,
"documentId": "z5jnfvyuj07fogzh1kcbd3",
"title": "7 Places worth visiting for the food alone",
"slug": "7-places-worth-visiting-for-the-food-alone",
"createdAt": "2021-11-12T13:33:19.948Z",
"updatedAt": "2023-06-02T11:30:00.075Z",
"publishedAt": "2023-06-02T11:30:00.075Z",
"locale": "en",
"ckeditor_content": "…", // … truncated content
"blocks": [
{
"id": 1,
"documentId": "ks7xsp9fewoi0qljcz9qa0",
"__component": "blocks.related-articles",
"articles": {
// …
}
},
{
"id": 1,
"documentId": "c2imt19iywk27hl2ftph7s",
"__component": "blocks.cta-command-line",
"theme": "secondary",
"title": "Want to give it a try with a brand new project?",
"text": "Up & running in seconds 🚀",
"commandLine": "npx create-strapi-app my-project --quickstart"
}
]
},
{
"id": 4,
// …
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 4
}
}
}