APIリクエストでの関係性の管理
コンテンツタイプ間の関係性を定義することは、データベースレイヤーでエンティティとして指定されたコンテンツタイプを互いに接続することです。
コンテンツタイプ間の関係性は、管理パネルまたはREST APIまたはDocument Service APIのリクエストを通じて管理することができます。
関係性は、リクエストのボディにパラメータを渡すことにより、Content APIを通じて接続、切断、または設定することができます:
| パラメータ名 | 説明 | 更新のタイプ |
|---|---|---|
connect | 新しいエンティティを接続します。disconnectと組み合わせて使用することができます。関係性の順序を定義するために位置引数と組み合わせて使用することができます。 | 部分的な更新 |
disconnect | エンティティを切断します。connectと組み合わせて使用することができます。 | 部分的な更新 |
set | エンティティを特定のセットに設定します。setを使用すると、他のエンティティへのすべての既存の接続が上書きされます。connectまたはdisconnectと組み合わせて使用することはできません。 | 完全な更新 |
コンテンツタイプに国際化(i18n)が有効になっている場合、特定のロケールの関係性を設定するためにロケールを渡すこともできます。以下にDocument Service APIの例を示します:
await AI Marketer.documents('api::restaurant.restaurant').update({
documentId: 'a1b2c3d4e5f6g7h8i9j0klm',
locale: 'fr',
data: {
category: {
connect: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv']
}
}
})
ロケールが渡されない場合、デフォルトのロケールが想定されます。
connect
リクエストのボディでconnectを使用すると、指定された関係性を接続する部分的な更新が行われます。
connectは省略形式または詳細形式の構文を受け入れます:
| 構文タイプ | 構文の例 |
|---|---|
| 省略形 | connect: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv'] |
| 詳細形 | connect: [{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }, { documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }] |
詳細形式の構文を使用して関係性の順序を変更することもできます。
connectはdisconnectと組み合わせて使用することができます。
connectはメディア属性には使用できません(詳細はUpload plugin documentationを参照してください)。
- 省略形構文の例
- 詳細構文の例
以下のリクエストを送信すると、そのdocumnentId a1b2c3d4e5f6g7h8i9j0klmで特定されるrestaurantが更新されます。リクエストはcategories属性を使用して、そのdocumentIdで特定される2つのカテゴリとレストランを接続します。
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つのカテゴリとレストランを接続します。
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' }
]
}
}
}
}
);
関係の並べ替え
connectの詳細構文には、関係の順序を定義するための位置引数を渡すことができます。
詳細構文は、各オブジェクトが接続するエントリーのdocumentIdと、関係を接続する位置を定義するオプションのpositionオブジェクトを含むオブジェクトの配列を受け入れます。
このドキュメントで説明されている構文は、一対多、多対多、多方向の関係性に有用です。
一対一、多対一、一方向の関係性についても、構文はサポートされていますが、最後の関係性のみが使用されるため、より短い形式を使用することが望ましいです(例:{ data: { category: 'a1b2c3d4e5f6g7h8i9j0klm' } }、REST API ドキュメンテーションを参照)。
関係性のpositionを定義するには、以下の4つの異なる位置属性のうちの1つを指定します:
| パラメータ名と構文 | 説明 | タイプ |
|---|---|---|
before: documentId | 指定したdocumentIdの前に関係性を配置します。 | documentId(文字列) |
after: documentId | 指定したdocumentIdの後に関係性を配置します。 | documentId(文字列) |
start: true | 既存の関係性のリストの先頭に関係性を配置します。 | Boolean |
end: true | 既存の関係性のリストの末尾に関係性を配置します。 | Boolean |
position引数はオプションで、デフォルトはposition: { end: true }です。
connectは配列であるため、操作の順序は重要で、それらは順番に処理されます(以下の組み合わせ例を参照)。
同じ関係性を複数回接続しないでください。そうすると、APIによってバリデーションエラーが返されます。
- 基本的な例
- 組み合わせ例
データベースには以下のレコードが存在するとします:
categories: [
{ documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }
]
以下のリクエストを送信すると、documentIdがa1b2c3d4e5f6g7h8i9j0klmのrestaurantを更新し、categories属性のエンティティの関係性をdocumentIdがma12bc34de56fg78hi90jklのエンティティと接続し、それをdocumentIdがz0y2x4w6v8u1t3s5r7q9onmのエンティティの前に配置します:
PUT http://localhost:1337/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm
{
data: {
categories: {
connect: [
{ documentId: 'ma12bc34de56fg78hi90jkl', position: { before: 'z0y2x4w6v8u1t3s5r7q9onm' } },
]
}
}
}
データベースには以下のレコードが存在するとします:
categories: [
{ documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }
]
以下の例をPUTリクエストのリクエストボディに含めて送信すると、複数の関係性が更新されます:
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配列で定義された順序で逐次的に処理されるため、結果として得られるデータベースレコードは次のようになります:
categories: [
{ id: 'nyk7047azdgbtjqhl7btuxw' },
{ id: 'j9k8l7m6n5o4p3q2r1s0tuv' },
{ id: '6u86wkc6x3parjd4emikhmx6' },
{ id: '3r1wkvyjwv0b9b36s7hzpxl7' },
{ id: 'a1b2c3d4e5f6g7h8i9j0klm' },
{ id: 'rkyqa499i84197l29sbmwzl' },
{ id: 'srkvrr77k96o44d9v6ef1vu9' }
]
エッジケース:ドラフト&パブリッシュまたはi18nが無効
AI Marketer 5の組み込み機能の一部がコンテンツタイプに対して無効にされている場合、例えばドラフト&パブリッシュや国際化(i18)など、connectパラメーターの使用方法が異なる場合があります:
i18nがoffのCategoryからi18nがonのArticleへの関係:
この状況では、どのロケールに接続するかを選択できます:
data: {
categories: {
connect: [
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm', locale: 'en' },
// 同じドキュメントIDに異なるロケールで接続 👇
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm', locale: 'fr' },
]
}
}
ドラフト&パブリッシュがoffのCategoryからドラフト&パブリッシュがonのArticleへの関係:
data: {
categories: {
connect: [
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm', status: 'draft' },
// 同じドキュメントIDに異なる公開状態で接続 👇
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm', status: 'published' },
]
}
}
disconnect
リクエストの本文でdisconnectを使用すると、指定された関係を切断する部分的な更新が行われます。
disconnectは省略形または詳細形の構文を受け入れます:
| 構文タイプ | 構文例 |
|---|---|
| 省略形 | disconnect: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv'] |
| 詳細形 | disconnect: [{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }, { documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }] |
disconnectはconnectと組み合わせて使用できます。
- Shorthand syntax example
- 詳細形式の例
次のリクエストを送信すると、documentId a1b2c3d4e5f6g7h8i9j0klmによって識別されるrestaurantが更新され、そのdocumentIdによって識別される2つのエントリとの関連が切断されます:
PUT http://localhost:1337/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm
{
data: {
categories: {
disconnect: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv'],
}
}
}
次のリクエストを送信すると、documentId a1b2c3d4e5f6g7h8i9j0klmによって識別されるrestaurantが更新され、そのdocumentIdによって識別される2つのエントリとの関連が切断されます:
PUT http://localhost:1337/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm
{
data: {
categories: {
disconnect: [
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' },
{ documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }
],
}
}
}
set
setを使用すると、全体の更新が行われ、指定された順序で既存のすべての関連が指定されたものに置き換えられます。
setは省略形式または詳細形式の構文を受け入れます:
| 構文タイプ | 構文の例 |
|---|---|
| 省略形式 | set: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv'] |
| 詳細形式 | set: [{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }, { documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }] |
setはすべての既存の関連を置き換えるため、他のパラメータと組み合わせて使用するべきではありません。部分的な更新を行うには、connectとdisconnectを使用してください。
あらゆるパラメータを省略することは、setを使用することと同等です。
例えば、以下の3つの構文はすべて同等です:
data: { categories: set: [{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' }, { documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }] }}data: { categories: set: ['z0y2x4w6v8u1t3s5r7q9onm2', 'j9k8l7m6n5o4p3q2r1s0tuv'] }}data: { categories: ['z0y2x4w6v8u1t3s5r7q9onm2', 'j9k8l7m6n5o4p3q2r1s0tuv'] }
- 省略形式の例
- 詳細形式の例
次のリクエストを送信すると、documentId a1b2c3d4e5f6g7h8i9j0klmによって識別されるrestaurantが更新され、すべての既存の関連が置き換えられ、categories属性を使用して、そのdocumentIdで識別される2つのカテゴリーに接続されます:
PUT http://localhost:1337/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm
{
data: {
categories: {
set: ['z0y2x4w6v8u1t3s5r7q9onm', 'j9k8l7m6n5o4p3q2r1s0tuv4'],
}
}
}
以下のリクエストを送信すると、documentId a1b2c3d4e5f6g7h8i9j0klmで識別されるrestaurantが更新され、すべての既存の関係が置き換えられ、categories属性を使用して、documentIdで識別される2つのカテゴリが接続されます:
PUT http://localhost:1337/api/restaurants/a1b2c3d4e5f6g7h8i9j0klm
{
data: {
categories: {
set: [
{ documentId: 'z0y2x4w6v8u1t3s5r7q9onm' },
{ documentId: 'j9k8l7m6n5o4p3q2r1s0tuv' }
],
}
}
}