Azure Cosmos DB JavaScript SDK 4.9.3で変わる現場ワークフロー|ORDER BYと継続トークンの実務対策

Azure Cosmos DB JavaScript SDK の rollout でまず見るべきポイントは、「新機能が増えたか」ではなく「ORDER BY と継続トークンを使うページング処理の信頼性が上がるか」です。2026年4月20日に公開された @azure/cosmos 4.9.3 では、ORDER BY クエリと継続トークンを組み合わせた際の SQL フィルター生成不具合が修正されました。特に、管理画面の一覧、CSVエクスポート、バックグラウンド集計、グローバル向け検索結果など、並び替えながらページ分割して取得する業務では、早めに影響範囲を確認すべき更新です。(GitHub)

目次

Azure Cosmos DB JavaScript SDK 4.9.3の最新動向

Azure Cosmos DB JavaScript SDK 4.9.3は、派手なAPI追加ではなく、実務上のデータ取得フローに関わるバグ修正が中心です。公式のリリース履歴では、ORDER BY クエリで継続トークンを使う際、orderByItem の値に含まれるバックスラッシュやシングルクォートが formatValueForSQL で適切にエスケープされるようになった、と説明されています。(GitHub)

この修正が重要なのは、問題が「例外が出る」タイプではなく、「ページング中に一部の行が正しく拾えない可能性がある」タイプだったためです。Pull Requestでは、バックスラッシュを含む文字列が Cosmos DB SQL パーサーにより Unicode エスケープや制御文字として解釈され、フィルターの不一致によってページング中に行がスキップされ得る、という根本原因が説明されています。(GitHub)

つまり、現場目線では次のように捉えると分かりやすいです。

観点4.9.3 rollout前に気にすべきこと4.9.3 rollout後に期待できること
管理画面の一覧名前、SKU、パス、メール、タイトルなどで ORDER BY しているか特殊文字を含むデータのページング確認がしやすくなる
CSV・帳票出力大量データを fetchNext() で分割取得しているか並び替え付きエクスポートの欠落検知テストを組み込みやすくなる
グローバル対応アポストロフィ、バックスラッシュ、エスケープ風文字列を含む入力があるか多言語・多地域データでの境界ケースを明示的に扱える
運用監視件数差分、重複、欠落を見ているかSDK更新を「依存関係更新」ではなく「データ品質改善」として扱える

rolloutの本質は「ページングの業務リスク」を減らすこと

Azure Cosmos DBでは、クエリ結果が大きい場合、RU不足、応答サイズ、実行時間、効率上の理由などで結果が複数ページに分割されます。MaxItemCount を指定すると1回の要求で返す項目数の上限を調整できますが、ページ分割そのものは Cosmos DB 側の実行条件にも左右されます。(Microsoft Learn)

そのため、SDKの小さな修正でも、現場では次のようなワークフローに影響します。

  • Power users が使う検索・一覧画面
  • admins が監査や運用確認で使うデータ抽出
  • solution owners が責任を持つ月次レポートや顧客向けAPI
  • サポート担当が問い合わせ調査で使う管理コンソール
  • 多言語データ、Windowsパス、コード値、外部IDを含むグローバルサービス

特に注意したいのは、fetchAll() を使っているから安全とは限らない点です。アプリケーションコードでは1回の呼び出しに見えても、結果が大きければ内部的にはページ分割されます。ORDER BY 付きの大量取得で、並び替え対象の値に特殊文字が混じるなら、4.9.3の修正対象に近い処理として確認すべきです。

影響を受けやすい利用シナリオ

管理画面で顧客や注文を並び替えて表示する

たとえば、管理者が「顧客名順」「更新日時順」「注文番号順」で一覧を確認する画面では、次のような実装がよくあります。

const querySpec = {
  query: `
    SELECT c.id, c.customerName, c.updatedAt
    FROM c
    WHERE c.tenantId = @tenantId
    ORDER BY c.customerName ASC
  `,
  parameters: [
    { name: "@tenantId", value: tenantId }
  ]
};

const queryIterator = container.items.query(querySpec, {
  partitionKey: tenantId,
  maxItemCount: 50,
  enableQueryControl: true,
  forceQueryPlan: true,
  continuationToken: inputContinuationToken
});

このような画面では、O'Brien のようなシングルクォートを含む氏名、C:\Users\... のようなパス文字列、\n や \u2013 のように見える文字列が並び替え対象に入ることがあります。4.9.3の修正は、こうした値が継続トークン経由で SQL フィルターに組み込まれる際の扱いに関係します。(GitHub)

実務では、SDKを更新するだけで終わらせず、次の観点でテストデータを作るのが有効です。

テストデータ例確認したいこと
O'Brienシングルクォートを含む値でページ欠落が起きないか
C:\temp\file.txtバックスラッシュを含む値で順序と件数が保たれるか
Gold\u2013PlanUnicodeエスケープ風の文字列が文字列として扱われるか
line\nbreak制御文字風の並びがページング結果に影響しないか
日本語名 + 記号グローバル・多言語データでも同じ確認ができるか

CSVエクスポートやバッチ処理で全件を分割取得する

CSV出力や夜間バッチでは、1回に全件を取らず、maxItemCount と継続トークンで分割取得する構成が一般的です。FeedOptions の maxItemCount は、最初の結果を早く返すか、大量取得のスループットを優先するかの調整に影響します。小さい値なら初回応答は速くなりやすく、大きい値なら大量処理の効率が上がる場合があります。(Microsoft Learn)

ただし、バッチ処理では「最後までエラーなく完了した」だけでは不十分です。rollout後の検証では、次のようなチェックを入れるべきです。

チェック項目実務での確認方法
取得件数同じ条件の COUNT 相当の結果や既存集計値と比較する
重複id をSetに入れて重複数をログに出す
欠落既知の特殊文字データを固定テストデータとして投入する
順序前ページ末尾と次ページ先頭の並び順を検証する
再開性保存した継続トークンから再開して同じ結果になるか確認する

継続トークンは「中身を解釈して使う文字列」ではなく、列挙を継続するための opaque token として扱うべきものです。FeedOptions でも continuationToken は列挙を継続するための不透明なトークンとされています。(Microsoft Learn)

グローバル向けサービスで多言語データを扱う

グローバル読者向けに特に重要なのは、問題の引き金になる値が「珍しいデータ」ではないことです。英語圏の人名や商品名にはシングルクォートが入ります。開発者向けサービスならパス、正規表現、コード片、SKUにバックスラッシュが入ります。多地域サービスでは、外部システムから \uXXXX のようなエスケープ風文字列がそのまま保存されることもあります。

つまり、4.9.3のrolloutは、単なるSDK更新ではなく「グローバルデータの境界ケースに対する品質保証」として扱うべきです。solution owner は、対象データに特殊文字がどれくらい含まれるかを開発チーム任せにせず、受け入れ基準に入れると失敗を減らせます。

実装時に見直したいページング処理

Microsoft Learnの JavaScript SDK ドキュメントでは、継続トークンを使うクエリでは enableQueryControl を true にする例が示されています。また、ORDER BY クエリでは特別な扱いが必要で、初期呼び出しで resources が空、continuationToken が undefined になる場合があるため、resources.length > 0 を確認するよう案内されています。(Microsoft Learn)

APIで1ページだけ返す実装では、空ページをそのままフロントエンドへ返すと、利用者には「データがない」と見えてしまいます。次のように、空の中間応答をスキップしてから返す設計にしておくと、管理画面やエクスポート処理での誤判定を減らせます。

async function fetchCustomerPage({
  container,
  tenantId,
  inputContinuationToken
}: {
  container: any;
  tenantId: string;
  inputContinuationToken?: string;
}) {
  const querySpec = {
    query: `
      SELECT c.id, c.customerName, c.updatedAt
      FROM c
      WHERE c.tenantId = @tenantId
      ORDER BY c.customerName ASC
    `,
    parameters: [{ name: "@tenantId", value: tenantId }]
  };

  const iterator = container.items.query(querySpec, {
    partitionKey: tenantId,
    maxItemCount: 50,
    enableQueryControl: true,
    forceQueryPlan: true,
    continuationToken: inputContinuationToken
  });

  while (iterator.hasMoreResults()) {
    const { resources, continuationToken } = await iterator.fetchNext();

    if (resources.length === 0) {
      continue;
    }

    return {
      items: resources,
      nextToken: continuationToken ?? null
    };
  }

  return {
    items: [],
    nextToken: null
  };
}

この実装例で重要なのは、SDK更新そのものよりも、アプリケーション側が「空の途中ページ」と「本当に結果がない状態」を区別することです。特にPower usersが使う管理画面では、1ページ目が空に見えただけで問い合わせや再実行が発生します。UIの問題に見えて、実際はSDK・クエリ・ページング設計が絡むケースです。

adminsとsolution ownersが取るべきrollout手順

4.9.3は、Azure SDK Releases上でも @azure/cosmos の npm 4.9.3として掲載され、サポート状態はActiveとされています。(Azure)

導入時は、いきなり本番全体へ展開するより、次の順序で進めると安全です。

手順実施内容判断基準
依存関係の棚卸し@azure/cosmos の利用箇所、バージョン、ロックファイルを確認複数サービスで異なるバージョンを使っていないか
クエリの抽出ORDER BY、continuationToken、fetchNext()、fetchAll() を検索並び替え付き大量取得があるか
リスク分類管理画面、エクスポート、バッチ、顧客向けAPIを分類件数欠落が業務影響につながるか
回帰テスト追加特殊文字を含む固定データでページングを確認件数、順序、重複、欠落が検知できるか
カナリア展開一部テナント、検証環境、低リスクAPIから更新RU、レイテンシ、エラー率、問い合わせ数が悪化しないか
本番展開ロックファイル込みでデプロイ旧SDKの継続トークンを長期再利用しない設計か

アップデートコマンドは、検証環境で次のように明示的にバージョン指定して実行します。

npm install @azure/[email protected]

monorepoや複数サービス構成では、package-lock.json、pnpm-lock.yaml、yarn.lock も確認してください。アプリAだけ4.9.3、バッチBは古いSDKという状態になると、同じCosmos DBを見ているのに再現性の確認が難しくなります。

すぐ更新すべきケース、慎重に検証すべきケース

すべての利用者が同じ緊急度で更新する必要はありません。次の基準で優先順位を付けると、adminsやsolution ownersが関係者に説明しやすくなります。

優先度該当するシステム対応方針
高ORDER BY と継続トークンで大量データを取得する管理画面・API早期に4.9.3へ更新し、特殊文字データで回帰テスト
高CSV、監査ログ、請求、レポートなど件数欠落が問題になる処理既存出力との件数比較を必ず実施
中fetchAll() で並び替え付き検索をしている処理結果件数が多い場合はページング影響を確認
中多言語名、パス、コード、外部IDを並び替え対象にしている処理グローバルデータの境界ケースをテスト
低point read、upsert、delete中心でクエリをほぼ使わない処理通常の依存関係更新サイクルで対応
低小規模データでページ分割が発生しにくい検証用アプリただし本番成長時のためにテストだけ追加

失敗しやすいポイント

継続トークンをアプリ側で解析しようとする

継続トークンはSDKやサービスが使う再開情報です。中身をデコードして、特定のフィールドを読んだり、文字列置換したりする設計は避けるべきです。保存する場合は、クエリ条件、SDKバージョン、並び順、テナントIDなどとひも付けて「その条件でのみ再利用する」扱いにします。

SDK更新だけで品質保証が終わったと考える

今回の修正は、特定条件でのページング結果に関わります。したがって、単体テストだけでなく、実データに近い値を投入した結合テストが重要です。Pull Requestでも、バックスラッシュ、引用符、Unicodeシーケンス、Windowsパス、SQLインジェクション風文字列などを含むエッジケースで検証したことが説明されています。(GitHub)

maxItemCountをページ番号の代わりに使う

Cosmos DBのページングは、一般的な「1ページ目、2ページ目」というページ番号方式とは相性がよくありません。継続トークンで「続きから読む」方式として設計するのが基本です。前ページへ戻るUIが必要な場合は、取得済みトークンの履歴をアプリ側で保持する、検索条件が変わったらトークンを破棄する、といった設計が必要です。

本番中の長期ジョブをまたいでSDKを切り替える

長時間動くバッチやエクスポートで、途中の継続トークンを保存して後から再開する場合、SDK更新のタイミングに注意が必要です。Microsoftのドキュメントでは、同じSDKバージョンを使用している限り継続トークンは期限切れにならない、と説明されています。(Microsoft Learn)

実務では、長期ジョブの途中でSDKを切り替えるより、ジョブ完了後に更新するか、更新後にトークンをリセットして再実行するほうが安全です。

現場で使える確認チェックリスト

rollout前に、次の項目をチームで確認してください。

チェック確認内容
バージョン@azure/cosmos が4.9.3へ更新され、ロックファイルも反映されている
クエリORDER BY を使う検索・一覧・エクスポートを洗い出した
ページングcontinuationToken、fetchNext()、fetchAll() の利用箇所を確認した
データシングルクォート、バックスラッシュ、Unicodeエスケープ風文字列を含むテストデータがある
件数更新前後で取得件数、重複、欠落を比較できる
UI空の中間応答を「データなし」と誤表示しない
運用SDKバージョン、クエリ条件、継続トークンの扱いをログで追える
ロールバック問題発生時に依存関係とデプロイを戻せる

まとめ:次に取るべき行動

Azure Cosmos DB JavaScript SDK 4.9.3のrolloutは、画面やAPIの見た目を大きく変える更新ではありません。しかし、ORDER BY と継続トークンを使うページング処理では、データの欠落や誤表示を防ぐための重要な更新です。

まずは、ORDER BY、continuationToken、fetchNext()、fetchAll() を使っている箇所を検索してください。次に、特殊文字を含むデータで、件数・順序・重複・欠落を確認する回帰テストを追加します。そのうえで、管理画面やエクスポートなど業務影響が大きいワークフローから、4.9.3への更新を段階的に進めるのが現実的です。

Power usersには「一覧や出力結果の信頼性が上がる更新」、adminsには「依存関係と運用ログを整える更新」、solution ownersには「グローバルデータ品質を守る更新」と説明すると、単なるSDKアップデートではなく、業務フロー全体の改善としてrolloutを進めやすくなります。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次