管理与 API 请求的关系
🌐 Managing relations with API requests
Page summary:在 REST 和 GraphQL API 请求中使用
connect、disconnect和set参数来管理内容类型之间的关系。使用位置参数如before、after、start或end对关系进行重新排序。🌐 Use
connect,disconnect, andsetparameters in REST and GraphQL API requests to manage relations between content-types. Reorder relations using positional arguments likebefore,after,start, orend.
定义内容类型(在数据库层中指定为实体)之间的关系是将实体相互连接起来。
🌐 Defining relations between content-types (that are designated as entities in the database layers) is connecting entities with each other.
内容类型之间的关系可以通过管理面板或通过REST API或文档服务 API请求进行管理。
🌐 Relations between content-types can be managed through the admin panel or through REST API or Document Service API requests.
关系可以通过内容 API 连接、断开或设置,只需在请求的主体中传递参数。这些有效负载适用于单条条目关系和多重关系(一对多、多对一、多对多及多向)。当关系字段允许多个链接时,API 需要关系 ID 的数组,并在响应中返回数组。
🌐 Relations can be connected, disconnected or set through the Content API by passing parameters in the body of the request. These payloads work for both single-entry relations and multi relations (one-to-many, many-to-one, many-to-many, and many-way). When a relational field allows multiple links, the API expects arrays of relation IDs and returns arrays in responses.
| 参数名称 | 描述 | 更新类型 |
|---|---|---|
connect | 连接新实体。 可以与 disconnect 结合使用。可以与 位置参数 一起使用,以定义关系的顺序。 | 部分 |
disconnect | 断开实体连接。 可以与 connect 结合使用。 | 部分 |
set | 将实体设置为特定集合。使用 set 会覆盖与其他实体的所有现有连接。不能与 connect 或 disconnect 一起使用。 | 完整 |
本页描述的 connect、disconnect 和 set 有效负载适用于 REST 和 GraphQL 请 求,并且在从服务器或插件代码调用 文档服务 方法时也支持相同的对象结构。文档服务介绍部分重复了这一点,而本页稍下方的国际化示例显示了 strapi.documents(...).update() 和 connect。
🌐 The connect, disconnect, and set payloads described on this page apply to REST and GraphQL requests, and the same object shapes are supported when you call Document Service methods from server or plugin code. The Document Service introduction repeats this, and the Internationalization example further down on this page shows strapi.documents(...).update() with connect.
如果 TypeScript 报告 TS2353 并声称 connect 不是你的 data 对象上的有效属性,同时你照搬了这些示例,请将其视为类型定义的缺口,而不是 Strapi 在运行时拒绝调用。在 Strapi 类型包完全对齐之前,可以通过类型断言缩小 data 的负载,或者通过一个类型更宽松的小型辅助构建它,以便保留文档中描述的形状。有关讨论,请参见 GitHub issue #2904 。
🌐 If TypeScript reports TS2353 and claims connect is not a valid property on your data object while you mirror these examples, treat that as a typings gap rather than Strapi rejecting the call at runtime. Until the Strapi type packages align fully, narrow the data payload with a type assertion or build it through a small helper typed more loosely so you can keep the documented shape. See GitHub issue #2904 for discussion.
当在内容类型上启用国际化 (i18n)时,你还可以传递一个语言环境以为特定语言环境设置关系,如在此文档服务 API 示例中所示:
🌐 When Internationalization (i18n) is enabled on the content-type, you can also pass a locale to set relations for a specific locale, as in this Document Service API example:
await strapi.documents('api::restaurant.restaurant').update({
documentId: 'a1b2c3d4e5f6g7h8i9j0klm',
locale: 'fr',
data: {
category: {
connect: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv']
}
}
})
在 TypeScript 中使用 Document Service API 的 connect、disconnect 或 set 时,你可能会遇到 TS2353 错误,提示这些属性在 LongHandEntity 类型上不存在。
🌐 When using connect, disconnect, or set with the Document Service API in TypeScript, you may encounter a TS2353 error stating that these properties do not exist on type LongHandEntity.
虽然运行时引擎完全支持这种语法,但当前的类型定义不支持。你可以通过将数据负载转换为 any 或更广泛的对象类型来安全地跳过此验证:
🌐 While the runtime engine fully supports this syntax, the current typings do not. You can safely bypass this validation by casting your data payload to any or a broader object type:
await strapi.documents('api::cart.cart').update({
documentId: cart.documentId,
data: {
status: 'checked_out',
order: { connect: [order.documentId] } as any, // Temporary workaround
},
});
如果未传递任何语言环境,则将假定使用默认语言环境。
🌐 If no locale is passed, the default locale will be assumed.
connect
在请求体中使用 connect 会执行部分更新,连接指定的关系。
🌐 Using connect in the body of a request performs a partial update, connecting the specified relations.
connect 接受简写或长写语法:
| 语法类型 | 语法示例 |
|---|---|
| 简写 | connect: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv'] |
| 全写 | connect: [{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }, { documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }] |
你也可以使用长格式语法来重新排序关系。
🌐 You can also use the longhand syntax to reorder relations.
connect 可以与 disconnect 结合使用。
connect 官方不支持媒体属性。高级用户在技术上可以通过定位上传的文件 ID 来连接媒体条目,但这种方法不被 Strapi 推荐或支持,并且很容易出错(例如,当草稿与发布使用不匹配的 ID 时)。请谨慎操作。
- Shorthand syntax example
- Longhand syntax example
发送以下请求会更新一个由其 documnentId a1b2c3d4e5f6g7h8i9j0klm 标识的 restaurant。该请求使用 categories 属性将餐厅与由其 documentId 标识的 2 个类别关联起来:
🌐 Sending the following request updates a restaurant, identified by its documnentId a1b2c3d4e5f6g7h8i9j0klm. The request uses the categories attribute to connect the restaurant with 2 categories identified by their documentId:
PUT http://localhost:1337/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm
{
data: {
categories: {
connect: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv']
}
}
}
const fetch = require('node-fetch');
const response = await fetch(
'http://localhost:1337/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm',
{
method: 'put',
body: {
data: {
categories: {
connect: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv']
}
}
}
}
);
发送以下请求会更新一个 由其 documnentId a1b2c3d4e5f6g7h8i9j0klm 标识的 restaurant。该请求使用 categories 属性将餐厅与由其 documentId 标识的 2 个类别关联起来:
🌐 Sending the following request updates a restaurant, identified by its documnentId a1b2c3d4e5f6g7h8i9j0klm. The request uses the categories attribute to connect the restaurant with 2 categories identified by their documentId:
PUT http://localhost:1337/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm
{
data: {
categories: {
connect: [
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' },
{ documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }
]
}
}
}
const fetch = require('node-fetch');
const response = await fetch(
'http://localhost:1337/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm',
{
method: 'put',
body: {
data: {
categories: {
connect: [
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' },
{ documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }
]
}
}
}
}
);
关系重新排序
🌐 Relations reordering
4.6.0This feature requires Strapi version 4.6.0 or later.可以将位置参数传递给 connect 的长格式语法,以定义关系的顺序。
🌐 Positional arguments can be passed to the longhand syntax of connect to define the order of relations.
长格式语法接受一个对象数组,每个对象包含要连接条目的 documentId,以及用于定义连接关系位置的可选 position 对象。
🌐 The longhand syntax accepts an array of objects, each object containing the documentId of the entry to be connected and an optional position object to define where to connect the relation.
本文件中描述的语法对于一对多、多对多和多向关系非常有用。
对于一对一、多对一和单向关系,这些语法也被支持,但只会使用最后一个关系,因此建议使用较短的格式(例如:{ data: { category: 'a1b2c3d4e5f6g7h8i9j0klm' } },参见 REST API 文档)。
要为一 个关系定义 position,请传递以下四个不同的位置属性之一:
🌐 To define the position for a relation, pass one of the following 4 different positional attributes:
| 参数名称和语法 | 描述 | 类型 |
|---|---|---|
before: documentId | 将关系放置在给定的 documentId 之前。 | documentId (字符串) |
after: documentId | 将关系放置在给定的 documentId 之后。 | documentId (字符串) |
start: true | 将关系放置在现有关系列表的开头。 | 布尔值 |
end: true | 将关系放置在现有关系列表的末尾。 | 布尔值 |
position 参数是可选的,默认值为 position: { end: true }。
🌐 The position argument is optional and defaults to position: { end: true }.
由于 connect 是一个数组,操作的顺序很重要,因为它们将被按顺序处理(见下面的组合示例)。
🌐 Since connect is an array, the order of operations is important as they will be treated sequentially (see combined example below).
同一关系不应连接多次,否则 API 将返回验证错误。
🌐 The same relation should not be connected more than once, otherwise it would return a Validation error by the API.
- Basic example
- Combined example
考虑数据库中的以下记录:
🌐 Consider the following record in the database:
categories: [
{ documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }
]
发送以下请求会更新一个 restaurant,通过其 documentId a1b2c3d4e5f6g7h8i9j0klm 进行标识,将一个实体的关系连接到具有 ma12bc34de56fg78hi90jkl 的 documentId 上用于 categories 属性,并将其定位在具有 documentId z0y2x4w6v8u1t3s5r7q9onm 的实体之前:
🌐 Sending the following request updates a restaurant, identified by its documentId a1b2c3d4e5f6g7h8i9j0klm, connecting a relation of entity with a documentId of ma12bc34de56fg78hi90jkl for the categories attribute and positioning it before the entity with documentId z0y2x4w6v8u1t3s5r7q9onm:
PUT http://localhost:1337/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm
{
data: {
categories: {
connect: [
{ documentId: 'ma12bc34de56fg78hi90jkl', position: { before: 'z0y2x4w6v8u1t3s5r7q9onm' } },
]
}
}
}
考虑数据库中的以下记录:
🌐 Consider the following record in the database:
categories: [
{ documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }
]
在 PUT 请求的请求正文中发送以下示例会更新多个关系:
🌐 Sending the following example in the request body of a PUT request updates multiple relations:
PUT http://localhost:1337/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm
{
data: {
categories: {
connect: [
{ id: '6u86wkc6x3parjd4emikhmx', position: { after: 'j9k8l7m6n5o4p3q2r1s0tuv'} },
{ id: '3r1wkvyjwv0b9b36s7hzpxl', position: { before: 'z0y2x4w6v8u1t3s5r7q9onm' } },
{ id: 'rkyqa499i84197l29sbmwzl', position: { end: true } },
{ id: 'srkvrr77k96o44d9v6ef1vu' },
{ id: 'nyk7047azdgbtjqhl7btuxw', position: { start: true } },
]
}
}
}
省略 position 参数(如 documentId: 'srkvrr77k96o44d9v6ef1vu9')默认为 position: { end: true }。所有其他关系都是相对于另一个已存在的 id(使用 after 或 before)或相对于关系列表(使用 start 或 end)定位的。操作按 connect 数组中定义的顺序依次处理,因此生成的数据库记录将如下所示:
🌐 Omitting the position argument (as in documentId: 'srkvrr77k96o44d9v6ef1vu9') defaults to position: { end: true }. All other relations are positioned relative to another existing id (using after or before) or relative to the list of relations (using start or end). Operations are treated sequentially in the order defined in the connect array, so the resulting database record will be the following:
categories: [
{ id: 'nyk7047azdgbtjqhl7btuxw' },
{ id: 'j9k8l7m6n5o4p3q2r1s0tuv' },
{ id: '6u86wkc6x3parjd4emikhmx6' },
{ id: '3r1wkvyjwv0b9b36s7hzpxl7' },
{ id: 'a1b2c3d4e5f6g7h8i9j0klm' },
{ id: 'rkyqa499i84197l29sbmwzl' },
{ id: 'srkvrr77k96o44d9v6ef1vu9' }
]
边缘情况:草稿与发布或国际化禁用
🌐 Edge cases: Draft & Publish or i18n disabled
当 Strapi 5 的某些内置功能在内容类型中被禁用时,例如 草稿与发布 和 国际化 (i18n),connect 参数可能会有不同的使用方式:
🌐 When some built-in features of Strapi 5 are disabled for a content-type, such as Draft & Publish and Internationalization (i18), the connect parameter might be used differently:
从 i18n 关闭 的 Category 到 i18n 开启 的 Article 的关系:
在这种情况下,你可以选择要连接到哪个语言环境:
🌐 In this situation you can select which locale you are connecting to:
data: {
categories: {
connect: [
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm', locale: 'en' },
// Connect to the same document id but with a different locale 👇
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm', locale: 'fr' },
]
}
}
从 Draft & Publish 关闭 的 Category 到 Draft & Publish 开启 的 Article 的关系:
data: {
categories: {
connect: [
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm', status: 'draft' },
// Connect to the same document id but with different publication states 👇
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm', status: 'published' },
]
}
}
disconnect
在请求的主体中使用 disconnect 会执行部分更新,断开指定的关联。
🌐 Using disconnect in the body of a request performs a partial update, disconnecting the specified relations.
disconnect 接受简写或长写语法:
| 语法类型 | 语法示例 |
|---|---|
| 简写 | disconnect: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv'] |
| 全写 | disconnect: [{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }, { documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }] |
disconnect 可以与 connect 结合使用。
- Shorthand syntax example
- Longhand syntax example
发送以下请求会更新一个 restaurant,该 restaurant 由其 documentId a1b2c3d4e5f6g7h8i9j0klm 标识,同时断开与两个由其 documentId 标识的条目的关系:
🌐 Sending the following request updates a restaurant, identified by its documentId a1b2c3d4e5f6g7h8i9j0klm, disconnecting the relations with 2 entries identified by their documentId:
PUT http://localhost:1337/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm
{
data: {
categories: {
disconnect: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv'],
}
}
}
发送以下请求会更新一个 restaurant,该 restaurant 由其 documentId a1b2c3d4e5f6g7h8i9j0klm 标识,同时断开与两个由其 documentId 标识的条目的关系:
🌐 Sending the following request updates a restaurant, identified by its documentId a1b2c3d4e5f6g7h8i9j0klm, disconnecting the relations with 2 entries identified by their documentId:
PUT http://localhost:1337/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm
{
data: {
categories: {
disconnect: [
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' },
{ documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }
],
}
}
}
set
使用 set 会执行完整更新,用指定的顺序用指定的关系替换所有现有关系。
🌐 Using set performs a full update, replacing all existing relations with the ones specified, in the order specified.
set 接受简写或长写语法:
| 语法类型 | 语法示例 |
|---|---|
| 简写 | set: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv'] |
| 全写 | set: [{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }, { documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }] |
由于 set 会替换所有现有关系,因此不应与其他参数一起使用。要执行 部分更新,请使用 connect 和 disconnect。
🌐 As set replaces all existing relations, it should not be used in combination with other parameters. To perform a partial update, use connect and disconnect.
省略任何参数等同于使用 set。
例如,以下三种语法都是等效的:
data: { categories: set: [{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }, { documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }] }}data: { categories: set: ['z0y2x4w6v8u1t3s5r7q9onm2', 'j9k8l7m6n5o4p3q2r1s0tuv'] }}data: { categories: ['z0y2x4w6v8u1t3s5r7q9onm2', 'j9k8l7m6n5o4p3q2r1s0tuv'] }
- Shorthand syntax example
- Longhand syntax example
发送以下请求会更新一个 restaurant,该 restaurant 由其 documentId a1b2c3d4e5f6g7h8i9j0klm 标识,替换所有之前存在的关系,并使用 categories 属性连接由其 documentId 标识的两个类别:
🌐 Sending the following request updates a restaurant, identified by its documentId a1b2c3d4e5f6g7h8i9j0klm, replacing all previously existing relations and using the categories attribute to connect 2 categories identified by their documentId:
PUT http://localhost:1337/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm
{
data: {
categories: {
set: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv4'],
}
}
}
发送以下请求会更新一个 restaurant,该 restaurant 由其 documentId a1b2c3d4e5f6g7h8i9j0klm 标识,替换所有之前存在的关系,并使用 categories 属性连接由其 documentId 标识的两个类别:
🌐 Sending the following request updates a restaurant, identified by its documentId a1b2c3d4e5f6g7h8i9j0klm, replacing all previously existing relations and using the categories attribute to connect 2 categories identified by their documentId:
PUT http://localhost:1337/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm
{
data: {
categories: {
set: [
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' },
{ documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }
],
}
}
}