다음을 통해 공유


Azure Cosmos DB 부분 문서 업데이트 시작

적용 대상: NoSQL

이 문서에서는 .NET, Java, Node SDK에서 부분 문서 업데이트를 사용하는 방법을 보여 주는 예제를 제공합니다. 또한 발생할 수 있는 일반적인 오류에 대해서도 설명합니다.

이 문서에서는 다음 시나리오에 대한 코드 샘플에 연결합니다.

  • 단일 패치 작업 실행
  • 여러 패치 작업 결합
  • 필터 조건자를 기준으로 조건부 패치 구문 사용
  • 트랜잭션의 일부로 패치 작업 실행

필수 조건

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번째 자식이 있어야 합니다.

다음 단계