你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
Azure Cosmos DB 中的部分文档更新
适用范围: NoSQL
Azure Cosmos DB 部分文档更新功能(也称为补丁 API)提供了一种在容器中修改文档的便捷方法。 目前,若要更新某个文档,客户端需要读取该文档,执行乐观并发控制检查(如有必要),在本地更新文档,然后将其作为整个文档通过网络发送以替换 API 调用。
部分文档更新功能显着改善了这种体验。 客户端仅发送文档中修改过的属性/字段,而不进行完整的文档替换操作。 此功能的主要优点包括:
- 提高开发人员的工作效率:提供方便的 API,以便于使用并能够有条件地更新文档。
- 性能改进:在客户端上避免额外的 CPU 周期,减少端到端延迟和网络带宽。
- 多区域写入:通过对同一文档中的离散路径进行部分更新,支持自动和透明的冲突解决方案。
注意
部分文档更新操作基于 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 修补文档:
[
{ "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"]
}
支持的操作
此表总结了此功能支持的操作。
注意
目标路径是指 JSON 文档中的某个位置
操作类型 | 说明 |
---|---|
添加 | Add 执行以下操作之一,具体取决于目标路径:• 如果目标路径指定了一个不存在的元素,则添加该元素。 • 如果目标路径指定了一个已存在的元素,则替换其值。 • 如果目标路径是有效的数组索引,则将新元素插入到指定索引处的数组中。 这会将现有元素移到新元素之后。 • 如果指定的索引等于数组的长度,它会向数组追加一个元素。 除了指定索引,也可以使用 - 字符。 它还会导致向数组追加元素。注意:指定的索引大于数组长度时会导致错误。 |
设置 | Set 操作与 Add 类似,但 Array 数据类型除外。 如果目标路径是有效的数组索引,则更新该索引处的现有元素。 |
将 | Replace 操作与 Set 类似,但它遵循严格的仅替换语义。 如果目标路径指定了不存在的元素或数组,则会导致错误。 |
删除 | Remove 执行以下操作之一,具体取决于目标路径:• 如果目标路径指定了一个不存在的元素,则会导致错误。 • 如果目标路径指定了一个已存在的元素,则将其删除。 • 如果目标路径是一个数组索引,则将其删除并将指定索引上方的任何元素都回移一个位置。 注意:如果指定的索引等于或大于数组长度,将导致错误。 |
增量 | 此运算符按指定的值增加字段。 它可以接受正值和负值。 如果字段不存在,它会创建字段并将其设置为指定值。 |
移动 | 此运算符删除指定位置的值,并将其添加到目标位置。 操作对象必须包含一个“from”成员,该成员是包含 JSON 指针值的字符串,其中的指针值引用目标文档中要从中移动值的位置。 必须存在“from”位置,操作才能成功。如果“path”位置建议的对象不存在,则会创建对象并将值设置为等于“from”位置的值 •如果“path”位置建议的对象已存在,则会将“path”位置的值替换为“from”位置的值 •“Path”属性不能是“from”JSON 位置的 JSON 子级 |
支持的模式
部分文档更新功能支持以下运算模式。 有关代码示例,请参阅入门文档。
单个文档补丁:可以根据文档 ID 和分区键对单个文档进行修补。 可以对单个文档执行多个修补操作。 最大限制为 10 次操作。
多文档补丁:同一分区键内的多个文档可以作为事务的一部分进行修补。 仅当所有操作均按所述顺序成功完成时,此多文档事务才会提交。 如果任何操作失败,将回滚整个事务。
条件更新:对于上述模式,也可以添加一个类似 SQL 的筛选器谓词(例如
from c where c.taskNum = 3
),如果不满足谓词中指定的前提条件,那么操作将失败。也可使用支持的 SDK 的批量 API 对多个文档执行一个或多个修补操作。
相似性和差异性
我们来比较一下支持的模式之间的相似之处和差别。
添加与设置
对于除 Array
之外的所有数据类型,Set
操作类似于 Add
。 在任何(有效)索引处执行 Add
操作后,都会在指定索引处添加一个元素,并且数组中的任何现有元素最终都会移到该元素之后。 此行为与更新指定索引处的现有元素的 Set
操作相反。
添加与替换
Add
操作添加一个不存在的属性(包括 Array
数据类型)。 如果属性不存在,则 Replace
操作失败(也适用于 Array
数据类型)。
设置与替换
Set
操作添加一个不存在的属性(除非存在 Array
)。 如果属性不存在,则 Replace
操作失败(也适用于 Array
数据类型)。
注意
如果用户希望某些属性始终存在并且允许断言/强制执行该属性,则 Replace
是一个不错的选项。
部分文档更新的 REST API 参考
Azure Cosmos DB REST API 提供对 Azure Cosmos DB 资源的编程访问权限,以创建、查询和删除数据库、文档集合和文档。 除了对集合中的 JSON 文档执行插入、替换、删除、读取、枚举和查询操作外,还可以对部分文档更新操作使用 PATCH
HTTP 方法。 请参阅 Azure Cosmos 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 帐户配置了多个写入区域,则冲突和冲突解决策略适用于文档级别,其中最后写入者胜出 (LWW
) 是默认的冲突解决策略。 对于部分文档更新,跨多个区域的修补操作会检测和解决更详细的路径级别上的冲突。
通过示例可以更好地理解冲突解决。
假设 Azure Cosmos DB 中有以下文档:
{
"id": 1,
"name": "John Doe",
"email": "jdoe@contoso.com",
"phone": ["12345", "67890"],
"level": "gold"
}
不同客户端跨不同区域并发发出修补操作:
Set
属性/level
为白金- 从
/phone
中Remove
67890
由于修补请求是针对文档中的非冲突路径发出的,因此这些请求会以透明方式自动解决冲突(与文档级别的“以最后写入者为准”相反)。
解决冲突后,客户端将看到以下文档:
{
"id": 1,
"name": "John Doe",
"email": "jdoe@contoso.com",
"phone": ["12345"],
"level": "platinum"
}
注意
如果在多个区域中同时修补文档的同一属性,则应用常规的冲突解决策略。
更改源
Azure Cosmos DB 中的更改源侦听容器中发生的任何更改,然后输出已更改的文档。 使用更改源,可看到文档的所有更新,包括部分和完整文档更新。 处理来自更改源中的项时,即使更新是修补操作的结果,也会返回完整的文档。
有关 Azure Cosmos DB 中的更改源的详细信息,请参阅 Azure Cosmos DB 中的更改源。