Azure Cosmos DB 부분 문서 업데이트 시작
적용 대상: NoSQL
이 문서에서는 .NET, Java, Node SDK에서 부분 문서 업데이트를 사용하는 방법을 보여 주는 예제를 제공합니다. 또한 발생할 수 있는 일반적인 오류에 대해서도 설명합니다.
이 문서에서는 다음 시나리오에 대한 코드 샘플에 연결합니다.
- 단일 패치 작업 실행
- 여러 패치 작업 결합
- 필터 조건자를 기준으로 조건부 패치 구문 사용
- 트랜잭션의 일부로 패치 작업 실행
필수 조건
- 기존 Azure Cosmos DB 계정.
- 기존 Azure 구독이 있는 경우 새 계정을 만듭니다.
- Azure 구독이 없는 경우 시작하기 전에 체험 계정을 만듭니다.
- 또는 커밋하기 전에 Azure Cosmos DB 평가판을 사용해 볼 수 있습니다.
Azure Cosmos DB .NET v3 SDK의 부분 문서 업데이트(패치 API)에 대한 지원은 버전 3.23.0부터 사용할 수 있습니다. NuGet 갤러리에서 다운로드할 수 있습니다.
참고 항목
GitHub의 .NET v3 샘플 리포지토리에서 전체 부분 문서 업데이트 샘플을 찾습니다.
단일 패치 작업을 실행합니다.
ItemResponse<Product> response = await container.PatchItemAsync<Product>( id: "e379aea5-63f5-4623-9a9b-4cd9b33b91d5", partitionKey: new PartitionKey("road-bikes"), patchOperations: new[] { PatchOperation.Replace("/price", 355.45) } ); Product updated = response.Resource;
여러 패치 작업을 결합합니다.
List<PatchOperation> operations = new () { PatchOperation.Add("/color", "silver"), PatchOperation.Remove("/used"), PatchOperation.Increment("/price", 50.00), PatchOperation.Add("/tags/-", "featured-bikes") }; ItemResponse<Product> response = await container.PatchItemAsync<Product>( id: "e379aea5-63f5-4623-9a9b-4cd9b33b91d5", partitionKey: new PartitionKey("road-bikes"), patchOperations: operations );
필터 조건자를 기준으로 조건부 패치 구문을 사용합니다.
PatchItemRequestOptions options = new() { FilterPredicate = "FROM products p WHERE p.used = false" }; List<PatchOperation> operations = new () { PatchOperation.Replace($"/price", 100.00), }; ItemResponse<Product> response = await container.PatchItemAsync<Product>( id: "e379aea5-63f5-4623-9a9b-4cd9b33b91d5", partitionKey: new PartitionKey("road-bikes"), patchOperations: operations, requestOptions: options );
트랜잭션의 일부로 패치 작업을 실행합니다.
TransactionalBatchPatchItemRequestOptions options = new() { FilterPredicate = "FROM products p WHERE p.used = false" }; List<PatchOperation> operations = new () { PatchOperation.Add($"/new", true), PatchOperation.Remove($"/used") }; TransactionalBatch batch = container.CreateTransactionalBatch( partitionKey: new PartitionKey("road-bikes") ); batch.PatchItem( id: "e379aea5-63f5-4623-9a9b-4cd9b33b91d5", patchOperations: operations, requestOptions: options ); batch.PatchItem( id: "892f609b-8885-44df-a9ed-cce6c0bd2b9e", patchOperations: operations, requestOptions: options ); TransactionalBatchResponse response = await batch.ExecuteAsync(); bool success = response.IsSuccessStatusCode;
서버 쪽 프로그래밍 지원
저장 프로시저, 트리거 및 사용자 정의 함수를 사용하여 부분 문서 업데이트 작업을 서버 쪽에서 실행할 수도 있습니다.
this.patchDocument = function (documentLink, patchSpec, options, callback) {
if (arguments.length < 2) {
throw new Error(ErrorCodes.BadRequest, sprintf(errorMessages.invalidFunctionCall, 'patchDocument', 2, arguments.length));
}
if (patchSpec === null || !(typeof patchSpec === "object" || Array.isArray(patchSpec))) {
throw new Error(ErrorCodes.BadRequest, errorMessages.patchSpecMustBeObjectOrArray);
}
var documentIdTuple = validateDocumentLink(documentLink, false);
var collectionRid = documentIdTuple.collId;
var documentResourceIdentifier = documentIdTuple.docId;
var isNameRouted = documentIdTuple.isNameRouted;
patchSpec = JSON.stringify(patchSpec);
var optionsCallbackTuple = validateOptionsAndCallback(options, callback);
options = optionsCallbackTuple.options;
callback = optionsCallbackTuple.callback;
var etag = options.etag || '';
var indexAction = options.indexAction || '';
return collectionObjRaw.patch(
collectionRid,
documentResourceIdentifier,
isNameRouted,
patchSpec,
etag,
indexAction,
function (err, response) {
if (callback) {
if (err) {
callback(err);
} else {
callback(undefined, JSON.parse(response.body), response.options);
}
} else {
if (err) {
throw err;
}
}
}
);
};
참고 항목
GitHub의 .js DocDbWrapperScript에서 validateOptionsAndCallback
의 정의를 찾아보세요.
패치 작업에 대한 샘플 저장 프로시저:
function patchDemo() {
var doc = {
"id": "exampleDoc",
"fields": {
"field1": "exampleString",
"field2": 20,
"field3": 40
}
};
var isAccepted = __.createDocument(__.getSelfLink(), doc, (err, doc) => {
if (err) {
throw err;
}
else {
getContext().getResponse().setBody("Example document successfully created.");
var patchSpec = [
{ "op": "add", "path": "/fields/field1", "value": "newExampleString" },
{ "op": "remove", "path": "/fields/field2" },
{ "op": "incr", "path": "/fields/field3", "value": 10 }
];
var isAccepted = __.patchDocument(doc._self, patchSpec, (err, doc) => {
if (err) {
throw err;
}
else {
getContext().getResponse().appendBody(" Example document successfully patched.");
}
});
if (!isAccepted) throw new Error("Patch wasn't accepted");
}
});
if (!isAccepted) throw new Error("Create wasn't accepted.");
}
문제 해결
다음은 이 기능을 사용하는 동안 발생할 수 있는 일반적인 오류 목록입니다.
오류 메시지 | 설명 |
---|---|
잘못된 패치 요청: 패치 사양 구문 확인 | 패치 작업 구문이 잘못되었습니다. 자세한 내용은 부분 문서 업데이트 사양을 참조하세요. |
잘못된 패치 요청: 시스템 속성 SYSTEM_PROPERTY 를 패치할 수 없습니다. |
시스템 생성 속성(예: _id , _ts , _etag , _rid )은 패치 작업을 사용하여 수정할 수 없습니다. 자세한 내용은 부분 문서 업데이트 FAQ를 참조하세요. |
패치 작업 수는 10을 초과할 수 없습니다. | 단일 패치 사양에 추가할 수 있는 패치 작업은 10개로 제한됩니다. 자세한 내용은 부분 문서 업데이트 FAQ를 참조하세요. |
작업(PATCH_OPERATION_INDEX ): 작업할 인덱스(ARRAY_INDEX )가 배열 범위를 벗어납니다. |
패치할 배열 요소의 인덱스가 범위를 벗어납니다. |
작업(PATCH_OPERATION_INDEX ): 대체할 노드(PATH )가 트랜잭션 초기에 제거되었습니다. |
패치하려는 경로가 없습니다. |
작업(PATCH_OPERATION_INDEX ): 제거할 노드(PATH )가 없습니다. 참고: 트랜잭션 초기에 제거되었을 수도 있습니다. |
패치하려는 경로가 없습니다. |
작업(PATCH_OPERATION_INDEX ): 바꿀 노드(PATH )가 없습니다. |
패치하려는 경로가 없습니다. |
작업(PATCH_OPERATION_INDEX )의 경우: 노드(PATH )는 숫자가 아닙니다. |
증분 작업은 정수 및 부동 소수점 수에만 작동할 수 있습니다. 자세한 내용은 지원되는 작업을 참조하세요. |
작업(PATCH_OPERATION_INDEX )의 경우: 추가 작업은 기존 노드(배열 또는 개체)의 자식 개체만 만들 수 있으며, 경로를 재귀적으로 만들 수 없습니다. PATH 외의 경로는 없습니다. |
자식 경로를 개체 또는 배열 노드 유형에 추가할 수 있습니다. 또한 n 번째 자식을 만들려면 n-1 번째 자식이 있어야 합니다. |
작업(PATCH_OPERATION_INDEX )의 경우: 지정된 작업은 기존 노드(배열 또는 개체)의 자식 개체만 만들 수 있으며, 경로를 재귀적으로 만들 수 없습니다. PATH 외의 경로가 없습니다. |
자식 경로를 개체 또는 배열 노드 유형에 추가할 수 있습니다. 또한 n 번째 자식을 만들려면 n-1 번째 자식이 있어야 합니다. |