Azure Cosmos DB の部分的ドキュメント更新

適用対象: NoSQL

Azure Cosmos DB の部分的ドキュメント更新機能 (パッチ API とも呼ばれます) には、コンテナー内のドキュメントを変更する便利な方法が用意されています。 現在のところ、ドキュメントを更新するには、クライアントを使用して読み取り、(必要に応じて) オプティミスティック同時実行制御チェックを実行し、ローカルでドキュメントを更新して、それをドキュメント全体の置換 API の呼び出しとしてネットワーク経由で送信します。

部分的ドキュメント更新機能により、このエクスペリエンスが大幅に向上します。 全ドキュメントの置き換え操作を行うことなく、クライアントからドキュメント内の変更されたプロパティとフィールドのみを送信することができます。 この機能の主な利点は次のとおりです。

  • 開発者の生産性の向上: 使いやすい API が用意されており、ドキュメントを条件付きで更新する機能があります。
  • パフォーマンスの向上: クライアント側の余計な CPU サイクルを回避し、エンドツーエンドの待機時間とネットワーク帯域幅を削減します。
  • マルチリージョンの書き込み: 同じドキュメント内の個別のパスを部分的に更新することで、自動的かつ透過的な競合解決をサポートします。

Note

"部分的ドキュメント更新" 操作は、JSON パッチ RFC に基づいています。 パス内のプロパティ名は、~ 文字と / 文字をそれぞれ ~0 および ~1 としてエスケープする必要があります。

ターゲット JSON ドキュメントの例:

{
  "id": "e379aea5-63f5-4623-9a9b-4cd9b33b91d5",
  "name": "R-410 Road Bicycle",
  "price": 455.95,
  "inventory": {
    "quantity": 15
  },
  "used": false,
  "categoryId": "road-bikes",
  "tags": ["r-series"]
}

JSON Patch ドキュメント:

[
  { "op": "add", "path": "/color", "value": "silver" },
  { "op": "remove", "path": "/used" },
  { "op": "set", "path": "/price", "value": 355.45 }
  { "op": "incr", "path": "/inventory/quantity", "value": 10 },
  { "op": "add", "path": "/tags/-", "value": "featured-bikes" },
  { "op": "move", "from": "/color", "path": "/inventory/color" }
]

結果の JSON ドキュメント:

{
  "id": "e379aea5-63f5-4623-9a9b-4cd9b33b91d5",
  "name": "R-410 Road Bicycle",
  "price": 355.45,
  "inventory": {
    "quantity": 25,
    "color": "silver"
  },
  "categoryId": "road-bikes",
  "tags": ["r-series", "featured-bikes"]
}

サポート対象の操作

この表は、この機能でサポートされている操作をまとめたものです。

Note

"ターゲット パス" は、JSON ドキュメント内の場所を指します。

演算の種類 説明
追加 Add により、ターゲット パスに応じて以下のいずれかが実行されます。
• ターゲット パスに存在しない要素が指定されている場合は、それが追加されます。
• ターゲット パスに存在する要素が指定されている場合、その値は置き換えられます。
• ターゲット パスが有効な配列インデックスの場合、指定されたインデックスの配列に新しい要素が挿入されます。 これにより、既存の要素が新しい要素の後にシフトされます。
• 指定されたインデックスが配列の長さと等しい場合は、配列に要素が追加されます。 インデックスを指定する代わりに、- 文字を使用することもできます。 また、配列に要素が追加されます。
: 配列の長さよりも大きいインデックスを指定すると、エラーが発生します。
Set Set の操作は、配列データ型の場合を除き、Add と似ています。 ターゲット パスが有効な配列インデックスの場合、そのインデックスの既存の要素は更新されます。
Replace Replace の操作は、"厳密な" 置換のみのセマンティクスに従うことを除き、Set と似ています。 ターゲット パスに存在しない要素や配列が指定された場合は、エラーが発生します。
Remove Remove により、ターゲット パスに応じて以下のいずれかが実行されます。
• ターゲット パスに存在しない要素が指定されている場合は、エラーが発生します。
• ターゲット パスに存在する要素が指定されている場合、それは削除されます。
• ターゲット パスが配列インデックスの場合、それは削除され、指定されたインデックスより上の要素は 1 つ後ろにシフトされます。
: 配列の長さ以上のインデックスを指定すると、エラーが発生します。
Increment この演算子を使うと、指定された値だけフィールドがインクリメントされます。 正の値と負の値の両方を指定できます。 フィールドが存在しない場合は、フィールドが作成され、指定された値が設定されます。
移動 この演算子を使うと、指定した場所にある値が削除され、ターゲットの場所に追加されます。 操作オブジェクトには、"from" メンバーが含まれている必要があります。これは、値の移動元となるターゲット ドキュメント内の場所を参照する JSON ポインター値を含む文字列です。 操作を成功させるには、"from" の場所が存在する必要があります。"path" の場所が、存在しないオブジェクトを示している場合、そのオブジェクトが作成され、"from" の場所の値と等しい値に設定されます
•"path" の場所が既に存在するオブジェクトを示している場合は、"path" の場所にある値を "from" の場所の値に置き換えます
•"Path" 属性を "from" JSON の場所の JSON の子にすることはできません

サポートされているモード

部分的ドキュメント更新機能は、次の操作モードをサポートしています。 コード例については、概要のドキュメントを参照してください。

  • 単一ドキュメントのパッチ: 1 つのドキュメントに対して、その ID とパーティション キーに基づいてパッチを適用できます。 1 つのドキュメントに対して複数のパッチ操作を実行することができます。 上限は 10 操作です。

  • 複数ドキュメントのパッチ: 同じパーティション キー内の複数のドキュメントに、トランザクションの一部としてパッチを適用できます。 このマルチドキュメント トランザクションは、すべての操作が記述された順序で成功した場合にのみコミットされます。 いずれかの操作が失敗した場合は、トランザクション全体がロールバックされます。

  • 条件付き更新: 前述のモードでは、SQL のようなフィルター述語 (たとえば、from c where c.taskNum = 3) を追加して、述語に指定された前提条件が満たされない場合に操作が失敗するようにすることもできます。

  • また、サポートされている SDK の一括 API を使用して、複数のドキュメントに対して 1 つ以上のパッチ操作を実行することもできます。

類似点と相違点

サポートされているモードの類似点と相違点を比較してみましょう。

追加と設定

Set 操作は、Array を除くすべてのデータ型で Add と似ています。 任意の (有効な) インデックスで Add 操作を行うと、指定されたインデックスに要素が追加され、配列内の既存の要素はすべて既存の要素の後ろにシフトされます。 この動作は、指定されたインデックスの既存の要素を更新する Set 操作とは対照的です。

追加と置換

Add 操作を使うと、(Array データ型を含め) プロパティがまだない場合は追加されます。 プロパティが存在しない場合、Replace 操作は失敗します (Array データ型にも適用されます)。

設定と置換

Set 操作を使うと、(Array があった場合を除き) プロパティがまだない場合は追加されます。 プロパティが存在しない場合、Replace 操作は失敗します (Array データ型にも適用されます)。

Note

Replace は、ユーザーがプロパティの一部が常に存在することを期待し、それをアサートまたは強制できる場合に適した候補です。

部分的ドキュメント更新に関する REST API リファレンス

Azure Cosmos DB REST API では、Azure Cosmos DB リソースへのプログラムによるアクセスにより、データベース、ドキュメント コレクション、ドキュメントを作成、クエリ、削除します。 コレクション内の JSON ドキュメントに対する挿入、置換、削除、読み取り、列挙、クエリ操作の実行に加えて、部分的なドキュメント更新操作には PATCH HTTP メソッドを使用できます。 詳細については、Azure Cosmos DB REST API リファレンスに関するページを参照してください。

たとえば、部分的なドキュメント更新を使用した set 操作に対する要求の外観を次に示します。

PATCH https://querydemo.documents.azure.com/dbs/FamilyDatabase/colls/FamilyContainer/docs/Andersen.1 HTTP/1.1
x-ms-documentdb-partitionkey: ["Andersen"]
x-ms-date: Tue, 29 Mar 2016 02:28:29 GMT
Authorization: type%3dmaster%26ver%3d1.0%26sig%3d92WMAkQv0Zu35zpKZD%2bcGSH%2b2SXd8HGxHIvJgxhO6%2fs%3d
Content-Type:application/json_patch+json
Cache-Control: no-cache
User-Agent: Microsoft.Azure.DocumentDB/2.16.12
x-ms-version: 2015-12-16
Accept: application/json
Host: querydemo.documents.azure.com
Cookie: x-ms-session-token#0=602; x-ms-session-token=602
Content-Length: calculated when request is sent
Connection: keep-alive
{
  "operations": [
    {
      "op": "set",
      "path": "/Parents/0/FamilyName",
      "value": "Bob"
    }
  ]
}

ドキュメント レベルとパス レベルの競合解決

Azure Cosmos DB アカウントが複数の書き込みリージョンで構成されている場合、競合と競合解決ポリシーはドキュメント レベルで適用され、Last Write Wins (LWW) が既定の競合解決ポリシーになります。 部分的ドキュメント更新の場合、複数のリージョンにまたがるパッチ操作により、より詳細なパス レベルでの競合の検出と解決が行われます。

競合解決は、例を挙げるとわかりやすくなります。

Azure Cosmos DB に次のようなドキュメントがあるとします。

{
  "id": 1,
  "name": "John Doe",
  "email": "jdoe@contoso.com",
  "phone": ["12345", "67890"],
  "level": "gold"
}

異なるクライアントは、異なるリージョン間で同時にパッチ操作を発行します。

  • 属性 /level を platinum に Set
  • 67890 を /phone から Remove

複数リージョンの同時の部分的更新操作での競合解決を示す画像。

Patch 要求はドキュメント内の競合しないパスに対して行われたので、これらの要求については、自動的かつ透過的に競合が解決されます (ドキュメント レベルの Last Writer Wins とは対照的です)。

競合の解決後、クライアントには次のようなドキュメントが表示されます。

{
  "id": 1,
  "name": "John Doe",
  "email": "jdoe@contoso.com",
  "phone": ["12345"],
  "level": "platinum"
}

Note

複数のリージョンでドキュメントの同じプロパティに対して同時にパッチが適用されている場合、通常の競合解決ポリシーが適用されます。

Change Feed

Azure Cosmos DB の変更フィードは、コンテナーに変更があるかを調べて、変更があったドキュメントを出力します。 変更フィードを使用すると、ドキュメントに対するすべての更新を、ドキュメントの部分的な更新と完全な更新の両方を含めて見ることができます。 変更フィードのアイテムを処理するとき、更新がパッチ操作の結果であった場合でも全ドキュメントが返されます。

Azure Cosmos DB の変更フィードの詳細については、「Azure Cosmos DB の変更フィード」を参照してください。

次のステップ

  • .NET、Java、Node を使用した部分的ドキュメント更新の概要について説明します。
  • 部分的ドキュメント更新についてよく寄せられる質問