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\u2013Plan | Unicodeエスケープ風の文字列が文字列として扱われるか |
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を進めやすくなります。

コメント