mcpField
V
vtex-io-masterdata

vtex-io-masterdata

github.com/vtexデータ・データベース471.2k 回インストール2 週間前に更新
リポジトリ

vtex-io-masterdata について

vtex-io-masterdataは、Master Data v2の保存方法を設計・実装するVTEX IO開発者向けスキルです。スキーマに基づくCRUD、検索、トリガー、ストア選定に加え、ガバナンスと誤用防止を解説します。

主な機能

  1. 01JSON Schemaによるエンティティ定義
  2. 02MasterDataClientを使ったCRUD操作
  3. 03検索とスクロールによる取得方法の選択
  4. 04インデックス、キャッシュ、セキュリティ、トリガーの設定
  5. 05Master Dataと他ストアの適合性評価

活用シーン

  1. 01レビューやフォーム投稿の保存先の設計
  2. 02スキーマに基づくVTEX IOデータアクセスの実装
  3. 03大量のドキュメントを取得する方法の設計
  4. 04データをMaster Dataと他の保存先のどちらに置くかの判断

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/vtex/skills --skill vtex-io-masterdata

インストール後、Claude Code で/vtex-io-masterdataを入力して読み込まれたか確認します。

詳細

MasterData v2 統合

このスキルを使用する場面

VTEX IO アプリでカスタムデータ(レビュー、お気に入りリスト、フォーム送信内容、設定レコード)を保存したり、そのデータをクエリまたはフィルタリングしたり、データ変更をトリガーとする自動ワークフローを設定したりする場合に、このスキルを使用します。また、Master Data と他の VTEX ストアや外部ストアのどちらを選ぶべきか、根拠を示す必要がある場合にも使用します。

  • masterdata ビルダーを使用してデータエンティティと JSON Schemas を定義する
  • MasterDataClient(ctx.clients.masterdata)を通じて CRUD 操作を実行する
  • 効率的なデータ取得のために、検索、スクロール、インデックス作成を設定する
  • 自動ワークフロー用に Master Data トリガーを設定する
  • 60 スキーマの上限を超えないよう、スキーマのライフサイクルを管理する
  • データを Catalog(フィールド、仕様、構造化されていない SKU/商品仕様)、Master Data、ネイティブの OMS/チェックアウト機能、または外部の SQL/NoSQL/データベースのどこに置くかを判断する
  • パフォーマンスと信頼性に関する明確な根拠がない限り、購入処理のクリティカルパス(カート、チェックアウト、決済、注文確定)での同期的な Master Data の利用を避ける
  • 単一の信頼できる情報源を優先する——利便性のために注文ヘッダーや OMS の一覧を Master Data に重複して保存せず、OMS またはキャッシュを備えた BFF を優先します(「関連スキル」を参照)

次の用途ではこのスキルを使用しないでください。

  • 一般的なバックエンドサービスのパターン(代わりに vtex-io-service-apps を使用)
  • GraphQL スキーマの定義(代わりに vtex-io-graphql-api を使用)
  • Manifest とビルダーの設定(代わりに vtex-io-app-structure を使用)

判断ルール

Master Data を選ぶ前に

アーキテクト、開発者、およびソリューションの設計または実装に関わる人は、十分に検討し、このセクションを既定の選択を批評するチェックリストとして扱ってください。Master Data が適切な永続化レイヤーなのかを改めて確認し、自動的に選ばないでください。このスキルは、利便性を優先した選択に疑問を投げかけるためのものです。

  • 目的 — Master Data はドキュメント指向のストアです(ドキュメント DB や DynamoDB のようなアクセスパターンに近いものです)。数ある選択肢の一つにすぎません。ワークロードとの適合性を検討せず、「そこにあるから」あるいは「安価だから」という理由で選ぶのは、設計上の問題です。
  • 商品に関するデータ — 情報が本質的に商品または SKU に関するものであれば、まず Catalog を評価してください。Catalog の実態を反映した並行する MD エンティティを作成する前に、仕様、構造化されていない商品/SKU 仕様、およびネイティブのカタログフィールドを検討します。
  • 購入処理 — レイテンシ予算や障害モードに関する根拠がない限り、チェックアウトの重要な処理経路(カートの変更、決済、注文確定)に、Master Data の同期的な読み取り/書き込みを含めないでください。ネイティブのコマースストアを使い、非同期処理または注文後のデータ拡充を優先します。
  • 注文と一覧 — My Orders などを提供するために OMS や注文データを Master Data に重複して保存すると、通常は単一の信頼できる情報源の原則に反します。二つ目の注文データベースを MD に作るのは「そのほうが簡単だから」という理由ではなく、アプリケーションキャッシュと適切な HTTP/パスセマンティクスを備えた BFF または IO レイヤーを介して、OMS API(またはマーケットプレイスプロトコル)を使ってください。
  • MD の公開 — Master Data はストレージにすぎません。ストアフロントやパートナーからアクセスさせる場合は、認証、認可、レート制限を適用するサービスを経由させてください。通常は、headless-bff-architecture のパターンに従う VTEX IO または外部 BFF を使用します。
  • MD が適している場合 — ストレージとの適合性を確認したうえで MD が適切であれば、以下のとおり CRUD とスキーマの規律を徹底してください。IO から HTTP または GraphQL を公開する場合は、vtex-io-application-performance および vtex-io-service-paths-and-cdn と組み合わせてください。
エンティティのガバナンスと適切な管理

新しいエンティティを作成したり、既存のエンティティを拡張したりする前に、現状を把握してください。

  • ネイティブエンティティ — プラットフォームは、CL(クライアント)、AD(住所)、OD(注文)、BK(ブックマーク)、AU(認証)などのエンティティを管理します。ネイティブエンティティの用途と重複するカスタムエンティティは決して作成しないでください。新しいエンティティを追加する前に、既存のエンティティを確認してください。
  • エンティティの利用状況の監査 — 数十個のカスタムエンティティを持つアカウントでは、それぞれの用途をログ/監視、キャッシュ/一時データ、注文の拡張、顧客の拡張、マーケティング、CMS/コンテンツ、連携/同期、認証/ID、物流/地理情報、カスタムビジネスロジックに分類してください。ログまたはキャッシュのカテゴリに属するエンティティは、誤用を示していることがよくあります。IO アプリのログは MD ではなくロガーに保存し、キャッシュは MD ではなく VBase に保存してください。
  • クリティカルパスのフラグ — エンティティがチェックアウト、カート、決済、ログインのフローで使用されているかを特定してください。クリティカルパス上のエンティティは、厳格なレイテンシと可用性の要件を満たす必要があります。MD エンティティがクリティカルパス上にある場合、そもそもそこに置くべきかどうかを検討してください。
  • ドキュメント数の把握 — REST-Range: resources=0-0 を指定した GET /search?_fields=id の REST-Content-Range ヘッダーを使うと、ドキュメントを取得せずに効率よく件数を数えられます。大規模なエンティティ(ドキュメント数が 10 万件以上)では、scrollDocuments、ページネーション戦略、場合によっては BFF キャッシュレイヤーが必要です。
一括操作とデータ移行

大規模なデータセットをインポート、エクスポート、または移行する場合:

  • インポート前の検証 — インポートデータを信頼できる情報源(例:SKU の検証にはカタログのエクスポート、メールアドレスの許可リストには CL エンティティまたはユーザー管理 API)と照合してください。MD に触れる前に、無効な行をまとめた例外レポートを作成してください。
  • JSONL ペイロード — 一括インポートでは、MD ドキュメントごとに 1 つの JSON オブジェクトを .jsonl ファイルに生成してください。これにより、1 行ずつ処理して途中から再開できます。
  • レート制限 — MD API にはレート制限があります。呼び出しの間に設定可能な遅延(例:400ms)を入れ、HTTP 429 レスポンスが返された場合は指数バックオフを使用してください。
  • チェックポイント — 大規模なインポート(ドキュメント数が 1 万件以上)では、進行状況をチェックポイントファイル(最後に成功したドキュメント ID または行インデックス)に保存してください。失敗またはタイムアウトが発生した場合は、最初からやり直さず、チェックポイントから再開してください。
  • 並列処理と同時実行数の制限 — 同時実行数を制限したプール(例:同時実行数 5〜10 の p-queue)を使って、POST または PATCH 操作を並列に実行してください。並列度が高すぎるとレート制限が発生し、低すぎると処理が遅くなります。
  • 再インポート前の一括削除 — エンティティ内のすべてのドキュメントを置き換える場合は、インポート前にスクロールして削除するか、同じチェックポイントとバックオフのパターンを使って、削除処理を別途実装してください。
  • スキーマとの整合性 — インポートペイロードがエンティティの JSON Schema と正確に一致することを確認してください。必須フィールドの欠落や型の不一致は、検証エラーが表面化しない原因になります。
実装ルール
  • データエンティティは、ドキュメントを格納する名前付きコレクション(データベーステーブルに相当)です。JSON Schemaは、構造、検証、インデックスを定義します。
  • masterdata ビルダーを使用する場合、エンティティはフォルダー構造 masterdata/{entityName}/schema.json で定義します。ビルダーは {vendor}_{appName}_{entityName} という名前のエンティティを作成します。
  • すべての CRUD 操作には、@vtex/clients の ctx.clients.masterdata または masterDataFor を使用してください。REST を直接呼び出すことはしないでください。
  • where 句で使用するすべてのフィールドは、効率的にクエリできるよう、スキーマの v-indexed 配列で宣言する必要があります。
  • 件数の上限が分かっている小規模な結果セット(最大ページサイズ 100)には searchDocuments を使用してください。大規模または上限のない結果セットには scrollDocuments を使用してください。
  • masterdata ビルダーはアプリのバージョンごとに新しいスキーマを作成します。エンティティあたりのスキーマ数のハードリミットである 60 件を超えないよう、使用されていないスキーマを削除してください。
v-* schema extensions(v-indexed、v-cache、v-security、v-triggers など)

Master Data v2 では、標準の JSON Schema を v-* プロパティで拡張し、インデックス作成、キャッシュ、セキュリティ、デフォルト値、トリガー、スキーマ継承を制御できます。各拡張機能の完全なリファレンス(使用する場面、使用しない場面、詳細な設定)については、vtex-io-masterdata-strategy スキルを参照してください。

IO アプリ開発で押さえておくべきポイントは次のとおりです。

  • v-indexed — where 句で使用するすべてのフィールドをここに指定する必要があります。インデックスを増やしすぎないでください。インデックスごとに書き込みのレイテンシが増加します。
  • v-cache — 読み取りが多いエンティティでは、デフォルトの true のままにします。高頻度で書き込みがあり、読み取り時に即時の一貫性が必要なエンティティでは false に設定します。
  • v-default-fields — 最小限にしてください。呼び出し元が fields を省略した場合に返される内容を制御します。
  • v-security — allowGetAll: false に設定し、publicRead/publicFilter で PII を公開しないでください。
  • v-triggers — メールや Webhook などの単純な自動処理に使用します。複雑なオーケストレーションには IO イベントを使用してください。

MasterDataClient のメソッド:

メソッド説明
getDocumentID で単一のドキュメントを取得します
createDocument新しいドキュメントを作成し、生成された ID を返します
createOrUpdateEntireDocumentドキュメント全体をアップサートします
createOrUpdatePartialDocument一部のフィールドをアップサートします(パッチ)
updateEntireDocument既存のドキュメントの全フィールドを置き換えます
updatePartialDocument特定のフィールドのみを更新します
deleteDocumentID でドキュメントを削除します
searchDocumentsフィルター、ページネーション、フィールド選択を指定して検索します
searchDocumentsWithPaginationInfo合計件数のメタデータを含めて検索します
scrollDocuments大量の検索結果を反復処理します

検索の where 句の構文:

where: "productId=12345 AND approved=true"
where: "rating>3"
where: "createdAt between 2025-01-01 AND 2025-12-31"

アーキテクチャ:

VTEX IO App (node builder)
  │
  ├── ctx.clients.masterdata.createDocument()
  │       │
  │       ▼
  │   Master Data v2 API
  │       │
  │       ├── Validates against JSON Schema
  │       ├── Indexes declared fields
  │       └── Fires triggers (if conditions match)
  │             │
  │             ▼
  │         HTTP webhook / Email / Action
  │
  └── ctx.clients.masterdata.searchDocuments()
          │
          ▼
      Master Data v2 (reads indexed fields for efficient queries)

厳守すべき制約

制約:MasterDataClient を使用する — REST を直接呼び出さない

VTEX IO アプリのすべての Master Data 操作は、MasterDataClient(ctx.clients.masterdata)または @vtex/clients の masterDataFor ファクトリーを経由する必要があります。/api/dataentities/ エンドポイントへの REST 呼び出しを直接行ってはいけません。

重要な理由

MasterDataClient は、認証トークンの挿入、リクエストのルーティング、再試行ロジック、キャッシュ、適切なエラー処理を行います。REST を直接呼び出すと、これらすべてを回避することになり、認証ヘッダー、ページネーション、再試行ロジックを手動で実装する必要があります。VTEX の認証トークン形式が変更された場合、直接呼び出しは動作しなくなりますが、クライアントを使用していれば透過的に処理されます。

検出

/api/dataentities/、api.vtex.com/api/dataentities に一致する URL への直接 HTTP 呼び出し、または Master Data エンドポイントを対象とする生の fetch/axios 呼び出しが見つかった場合は、代わりに ctx.clients.masterdata を使用するよう開発者に警告してください。

正しい例

// Using MasterDataClient through ctx.clients
export async function getReview(ctx: Context, next: () => Promise<void>) {
  const { id } = ctx.query;

  const review = await ctx.clients.masterdata.getDocument<Review>({
    dataEntity: "reviews",
    id: id as string,
    fields: [
      "id",
      "productId",
      "author",
      "rating",
      "title",
      "text",
      "approved",
    ],
  });

  ctx.status = 200;
  ctx.body = review;
  await next();
}

誤った例

// Direct REST call to Master Data — bypasses client infrastructure
import axios from "axios";

export async function getReview(ctx: Context, next: () => Promise<void>) {
  const { id } = ctx.query;

  // No caching, no retry, no proper auth, no metrics
  const response = await axios.get(
    `https://api.vtex.com/api/dataentities/reviews/documents/${id}`,
    {
      headers: {
        "X-VTEX-API-AppKey": process.env.VTEX_APP_KEY,
        "X-VTEX-API-AppToken": process.env.VTEX_APP_TOKEN,
      },
    },
  );

  ctx.status = 200;
  ctx.body = response.data;
  await next();
}

制約:すべてのデータエンティティに JSON Schema を定義する

アプリで使用するすべてのデータエンティティには、対応する JSON Schema が必要です。アプリをデプロイする前に、masterdata ビルダー(推奨)を使用するか、Master Data API で JSON Schema を作成してください。

重要な理由

スキーマがない場合、Master Data はドキュメントを非構造化 JSON として保存します。そのため、フィールドの検証もインデックス作成も行われず(大規模なデータセットでは検索が非常に遅くなります)、型安全性もトリガーのサポートもありません。インデックスのないフィールドへのクエリでは全件スキャンが実行され、タイムアウトしたり、レート制限に達したりする可能性があります。

検出

アプリがデータエンティティ内のドキュメントを作成または検索しているにもかかわらず、そのエンティティに JSON Schema が存在しない場合(masterdata/ ビルダーディレクトリまたは API のいずれにも存在しない場合)は、スキーマを定義するよう開発者に警告してください。

正しい例

{
  "$schema": "http://json-schema.org/schema#",
  "title": "review-schema-v1",
  "type": "object",
  "properties": {
    "productId": {
      "type": "string"
    },
    "author": {
      "type": "string"
    },
    "rating": {
      "type": "integer",
      "minimum": 1,
      "maximum": 5
    },
    "title": {
      "type": "string",
      "maxLength": 200
    },
    "text": {
      "type": "string",
      "maxLength": 5000
    },
    "approved": {
      "type": "boolean"
    },
    "createdAt": {
      "type": "string",
      "format": "date-time"
    }
  },
  "required": ["productId", "rating", "title", "text"],
  "v-default-fields": [
    "productId",
    "author",
    "rating",
    "title",
    "approved",
    "createdAt"
  ],
  "v-indexed": ["productId", "author", "approved", "rating", "createdAt"]
}

誤った例

// Saving documents without any schema — no validation, no indexing
await ctx.clients.masterdata.createDocument({
  dataEntity: "reviews",
  fields: {
    productId: "12345",
    rating: "five", // String instead of number — no validation!
    title: 123, // Number instead of string — no validation!
  },
});

// Searching on unindexed fields — full table scan, will time out on large datasets
await ctx.clients.masterdata.searchDocuments({
  dataEntity: "reviews",
  where: "productId=12345", // productId is not indexed — very slow
  fields: ["id", "rating"],
  pagination: { page: 1, pageSize: 10 },
});

制約:60 スキーマの上限に達しないよう、スキーマのバージョンを管理する

Master Data v2 のデータエンティティには、エンティティごとに 60 個のスキーマという上限があります。masterdata ビルダーを使用する場合、リンクまたはインストールされたアプリの各バージョンによって新しいスキーマが作成されます。未使用のスキーマは定期的に削除する必要があります。

重要な理由

60 個のスキーマの上限に達すると、masterdata ビルダーで新しいスキーマを作成できなくなり、新しいアプリバージョンのリンクまたはインストールも失敗します。これは引き上げられない、プラットフォームの厳格な上限です。

検出

アプリでリンクまたはインストールを何度も繰り返している場合は、Delete Schema API を使用して古いスキーマを確認し、クリーンアップするよう開発者に警告してください。

正しい例

# Periodically clean up unused schemas
# List schemas for the entity
curl -X GET "https://{account}.vtexcommercestable.com.br/api/dataentities/reviews/schemas" \
  -H "X-VTEX-API-AppKey: {appKey}" \
  -H "X-VTEX-API-AppToken: {appToken}"

# Delete old schemas that are no longer in use
curl -X DELETE "https://{account}.vtexcommercestable.com.br/api/dataentities/reviews/schemas/old-schema-name" \
  -H "X-VTEX-API-AppKey: {appKey}" \
  -H "X-VTEX-API-AppToken: {appToken}"

誤った例

Never cleaning up schemas during development.
After 60 link cycles, the builder fails:
"Error: Maximum number of schemas reached for entity 'reviews'"
The app cannot be linked or installed until old schemas are deleted.
制約:Master Data をログ、キャッシュ、一時ストレージとして使用しない

アプリケーションのログ記録、キャッシュ(IO アプリの状態、クエリ結果)、一時的なステージングデータに使用するエンティティは、Master Data に適しません。ログには ctx.vtex.logger、アプリ固有のキャッシュや一時状態には VBase、監査証跡には外部のログ集約サービスを使用してください。

重要な理由 — ログやキャッシュのエンティティには何百万ものドキュメントが蓄積し、レート制限に達し、エンティティが本来のクエリに使えなくなり、ストレージも無駄になります。MD は、書き込み頻度が高く、データ量が多い、破棄可能なデータ向けには設計されていません。

検出 — LOG、cache、temp、staging、debug のような名前のエンティティや、ビジネスイベントではなくトラフィック量に応じてドキュメント数が際限なく増えるエンティティが該当します。

正しい例

// Logs: use structured logger
ctx.vtex.logger.info({ action: "priceUpdate", skuId, newPrice });

// Cache: use VBase
await ctx.clients.vbase.saveJSON("my-cache", cacheKey, data);

誤った例

// Using MD as a log store — creates millions of documents
await ctx.clients.masterdata.createDocument({
  dataEntity: "appLogs",
  fields: {
    level: "info",
    message: `Price updated for ${skuId}`,
    timestamp: new Date(),
  },
});
制約:正当な理由なく、Master Data に並行する信頼できる唯一の情報源を作成しない

OMS、Catalog、または外部 ERP にすでに信頼できる唯一の情報源があるデータを Master Data に複製すると、たとえばカスタムリスト表示用の注文ヘッダーや、カタログ仕様で管理すべき SKU 属性を複製すると、データの不整合、照合作業のコスト、インシデントのリスクが生じます。

重要な理由

一部の処理の失敗、再試行、手動編集の後に、2 つの信頼できる情報源の内容が食い違います。チームは顧客の成果ではなく、同期やデバッグに時間を費やすことになります。

検出

BFF キャッシュの計画もなく、「パフォーマンスのため」に OMS の注文フィールドを重複させる新しい MD エンティティ、Catalog の仕様で十分なのに MD に保存されている商品属性、MD と OMS の不一致を「修正」するためのスケジュール済みジョブが該当します。

正しい例

1. Identify the authoritative system (OMS, Catalog, partner API).
2. Read from that source via BFF or IO, with caching (application + HTTP semantics) as needed.
3. Use MD only for data without a native home or after explicit architecture sign-off.

誤った例

"We store order snapshots in MD so the storefront is faster" while OMS remains canonical
and no reconciliation strategy exists — eventual inconsistency is guaranteed.

推奨パターン

masterdata ビルダーとポリシーを追加します。

{
  "builders": {
    "node": "7.x",
    "graphql": "1.x",
    "masterdata": "1.x"
  },
  "policies": [
    {
      "name": "outbound-access",
      "attrs": {
        "host": "api.vtex.com",
        "path": "/api/*"
      }
    },
    {
      "name": "ADMIN_DS"
    }
  ]
}

データエンティティのスキーマを定義します。

{
  "$schema": "http://json-schema.org/schema#",
  "title": "review-schema-v1",
  "type": "object",
  "properties": {
    "productId": {
      "type": "string"
    },
    "author": {
      "type": "string"
    },
    "email": {
      "type": "string",
      "format": "email"
    },
    "rating": {
      "type": "integer",
      "minimum": 1,
      "maximum": 5
    },
    "title": {
      "type": "string",
      "maxLength": 200
    },
    "text": {
      "type": "string",
      "maxLength": 5000
    },
    "approved": {
      "type": "boolean"
    },
    "createdAt": {
      "type": "string",
      "format": "date-time"
    }
  },
  "required": ["productId", "rating", "title", "text"],
  "v-default-fields": [
    "productId",
    "author",
    "rating",
    "title",
    "approved",
    "createdAt"
  ],
  "v-indexed": ["productId", "author", "approved", "rating", "createdAt"],
  "v-cache": false
}

masterDataFor でクライアントを設定します。

// node/clients/index.ts
import { IOClients } from "@vtex/api";
import { masterDataFor } from "@vtex/clients";

interface Review {
  id: string;
  productId: string;
  author: string;
  email: string;
  rating: number;
  title: string;
  text: string;
  approved: boolean;
  createdAt: string;
}

export class Clients extends IOClients {
  public get reviews() {
    return this.getOrSet("reviews", masterDataFor<Review>("reviews"));
  }
}

CRUD 操作を実装します。

// node/resolvers/reviews.ts
import type { ServiceContext } from "@vtex/api";
import type { Clients } from "../clients";

type Context = ServiceContext<Clients>;

export const queries = {
  reviews: async (
    _root: unknown,
    args: { productId: string; page?: number; pageSize?: number },
    ctx: Context,
  ) => {
    const { productId, page = 1, pageSize = 10 } = args;

    const results = await ctx.clients.reviews.search(
      { page, pageSize },
      [
        "id",
        "productId",
        "author",
        "rating",
        "title",
        "text",
        "createdAt",
        "approved",
      ],
      "", // sort
      `productId=${productId} AND approved=true`,
    );

    return results;
  },
};

export const mutations = {
  createReview: async (
    _root: unknown,
    args: {
      input: { productId: string; rating: number; title: string; text: string };
    },
    ctx: Context,
  ) => {
    const { input } = args;
    const email = ctx.vtex.storeUserEmail ?? "[email protected]";

    const response = await ctx.clients.reviews.save({
      ...input,
      author: email.split("@")[0],
      email,
      approved: false,
      createdAt: new Date().toISOString(),
    });

    return ctx.clients.reviews.get(response.DocumentId, [
      "id",
      "productId",
      "author",
      "rating",
      "title",
      "text",
      "createdAt",
      "approved",
    ]);
  },

  deleteReview: async (_root: unknown, args: { id: string }, ctx: Context) => {
    await ctx.clients.reviews.delete(args.id);
    return true;
  },
};

トリガーを設定します(任意)。

{
  "name": "notify-moderator-on-new-review",
  "active": true,
  "condition": "approved=false",
  "action": {
    "type": "email",
    "provider": "default",
    "subject": "New review pending moderation",
    "to": ["[email protected]"],
    "body": "A new review has been submitted for product {{productId}} by {{author}}."
  },
  "retry": {
    "times": 3,
    "delay": { "addMinutes": 5 }
  }
}

Service に組み込みます。

// node/index.ts
import type { ParamsContext, RecorderState } from "@vtex/api";
import { Service } from "@vtex/api";

import { Clients } from "./clients";
import { queries, mutations } from "./resolvers/reviews";

export default new Service<Clients, RecorderState, ParamsContext>({
  clients: {
    implementation: Clients,
    options: {
      default: {
        retries: 2,
        timeout: 5000,
      },
    },
  },
  graphql: {
    resolvers: {
      Query: queries,
      Mutation: mutations,
    },
  },
});

よくある失敗パターン

  • /api/dataentities/ への直接的な REST 呼び出し:axios や fetch を使って Master Data エンドポイントを呼び出すと、クライアントのインフラストラクチャを迂回するため、認証、キャッシュ、リトライが機能しません。代わりに ctx.clients.masterdata または masterDataFor を使用してください。
  • インデックス済みフィールドを使わずに検索する:インデックスされていないフィールドへのクエリは、ドキュメント全体のスキャンを引き起こします。大規模なデータセットでは、タイムアウトやレート制限エラーの原因になります。where 句で使用するすべてのフィールドがスキーマの v-indexed 配列に含まれていることを確認してください。
  • 検索結果のページネーションを行わない:Master Data v2 のページサイズの上限は 100 ドキュメントです。上限を超える件数を要求しても、エラーなしで上限までの結果のみが返されます。適切なページネーションを行うか、大規模な結果セットには scrollDocuments を使用してください。
  • 60 スキーマの上限を無視する:リンクまたはインストールされたアプリのバージョンごとに、新しいスキーマが作成されます。リンクを 60 回行うと、ビルダーが失敗します。Delete Schema API を使って、使用されていないスキーマを定期的に削除してください。
  • ログやキャッシュに MD を使用する:ビジネスイベントではなく、トラフィック量に応じて増加するエンティティです。ログやキャッシュのドキュメントが何百万件にもなると、アカウントの MD のパフォーマンスが低下します。
  • レート制限なしで一括インポートする:MD に並列書き込みを大量に行うと、429 エラーが発生し、アカウント全体でスロットリングが起きます。必ず同時実行数に上限を設け、バックオフを適用してください。
  • 検証せずにインポートする:カタログやユーザーストアとの相互参照を行わずにデータをインポートすると、孤立したドキュメントや参照の破損が発生し、スキーマ検証に失敗しても気付けないデータが生じます。
  • 一括操作でチェックポイントを使わない:5 万件のドキュメントのインポートが 3 万件目で失敗すると、チェックポイントファイルがなければ最初からやり直す必要があります。

レビューチェックリスト

  • manifest.json で masterdata ビルダーが宣言されていますか?
  • すべてのデータエンティティに、適切なフィールド定義を含む JSON Schema がありますか?
  • where 句で使うすべてのフィールドが v-indexed で宣言されていますか?
  • CRUD 操作では ctx.clients.masterdata または masterDataFor を使用していますか(REST の直接呼び出しをしていませんか)?
  • ページネーションは適切に処理されていますか(1 ページあたり最大 100 件、大規模なセットでは scroll)?
  • 60 スキーマの上限を回避するための、スキーマを整理する計画がありますか?
  • 必要なポリシー(outbound-access、ADMIN_DS)がマニフェストで宣言されていますか?
  • 商品または注文のデータに MD を使う前に、Catalog またはネイティブストアを採用するかどうかを検討しましたか?
  • 明確な根拠がない限り、MD は購入のクリティカルパスから外されていますか?
  • MD を外部に公開する場合、アクセスは認証を備えた制御された IO/BFF レイヤー経由ですか?
  • このエンティティは、ログ記録、キャッシュ、一時データに使用されていませんか?
  • 一括操作で、レート制限、バックオフ、チェックポイントが実装されていますか?
  • インポートデータは、MD に書き込む前に信頼できるデータソースと照合して検証されていますか?
  • ネイティブエンティティ(CL、AD、OD など)が特定され、カスタムエンティティで重複していませんか?

関連スキル

参考資料

コメント