Partilhar via


Introdução à atualização parcial de documentos do Azure Cosmos DB

Este artigo fornece exemplos que ilustram como usar a atualização parcial de documentos com SDKs .NET, Java e Node. Ele também descreve erros comuns que você pode encontrar.

Este artigo contém links para exemplos de código para os seguintes cenários:

  • Executar uma única operação de patch
  • Combine várias operações de patch
  • Usar sintaxe de patch condicional baseada no predicado de filtro
  • Executar operação de patch como parte de uma transação

Prerequisites

  • Uma conta existente do Azure Cosmos DB.

Usar atualização parcial de documentos

O suporte para atualização parcial de documentos (API de patch) no SDK do Azure Cosmos DB .NET v3 está disponível na versão 3.23.0 e posterior. Você pode baixar o pacote na galeria do NuGet.

Note

Encontre um exemplo completo de atualização parcial de documentos no repositório de exemplos do .NET v3 no GitHub.

  • Execute uma única operação de patch:

    ItemResponse<Product> response = await container.PatchItemAsync<Product>(
        id: "e4e4e4e4-ffff-aaaa-bbbb-c5c5c5c5c5c5",
        partitionKey: new PartitionKey("road-bikes"),
        patchOperations: new[] {
            PatchOperation.Replace("/price", 355.45)
        }
    );
    
    Product updated = response.Resource;
    
  • Combine várias operações de patch:

    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: "e4e4e4e4-ffff-aaaa-bbbb-c5c5c5c5c5c5",
        partitionKey: new PartitionKey("road-bikes"),
        patchOperations: operations
    );
    
  • Usar a sintaxe de patch condicional com base em um predicado de filtro

    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: "e4e4e4e4-ffff-aaaa-bbbb-c5c5c5c5c5c5",
        partitionKey: new PartitionKey("road-bikes"),
        patchOperations: operations,
        requestOptions: options
    );
    
  • Execute a operação de patch como parte de uma transação:

    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: "e4e4e4e4-ffff-aaaa-bbbb-c5c5c5c5c5c5",
        patchOperations: operations,
        requestOptions: options
    );
    batch.PatchItem(
        id: "f5f5f5f5-aaaa-bbbb-cccc-d6d6d6d6d6d6",
        patchOperations: operations,
        requestOptions: options
    );
    
    TransactionalBatchResponse response = await batch.ExecuteAsync();
    bool success = response.IsSuccessStatusCode;
    

Suporte para programação do lado do servidor

As operações de atualização parcial de documentos também podem ser executadas no lado do servidor usando procedimentos armazenados, gatilhos e funções definidas pelo usuário.

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;
                }
            }
        }
    );
}; 

Note

Encontre a definição de validateOptionsAndCallback no .js DocDbWrapperScript no GitHub.

Exemplo de procedimento armazenado para operação de patch:

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.");
}

Troubleshooting

Aqui estão alguns erros comuns que você pode encontrar ao usar esse recurso:

Mensagem de erro Description
Solicitação de patch inválida: verifique a sintaxe da especificação do patch. A sintaxe da operação de correção é inválida. Para saber mais, consulte a especificação.
Solicitação de patch inválida: Não é possível corrigir a propriedade SYSTEM_PROPERTYdo sistema . Propriedades geradas pelo sistema como _id, _ts, _etag, _rid não são modificáveis usando uma operação de patch. Para saber mais, consulte as Perguntas frequentes sobre atualização parcial de documentos.
O número de operações de patch não pode exceder 10. Há um limite de 10 operações de patch que podem ser adicionadas em uma única especificação de patch. Para saber mais, consulte as Perguntas frequentes sobre atualização parcial de documentos.
Para a operação(PATCH_OPERATION_INDEX): o índice(ARRAY_INDEX) a executar está fora dos limites do vetor. O índice do elemento do array a ser modificado está fora dos limites permitidos.
Para Operation(PATCH_OPERATION_INDEX)): Node(PATH) a ser substituído foi removido anteriormente na transação. O caminho que você está tentando corrigir não existe.
Para Operation(PATCH_OPERATION_INDEX): Node(PATH) a ser removido está ausente. Nota: também pode ter sido removido anteriormente na transação.  O caminho que você está tentando corrigir não existe.
Para Operation(PATCH_OPERATION_INDEX): Node(PATH) a ser substituído está ausente. O caminho que você está tentando corrigir não existe.
Para Operation(PATCH_OPERATION_INDEX): Node(PATH) não é um número. A operação de incremento funciona apenas com números inteiros e valores de ponto flutuante. Para obter mais informações, consulte Operações suportadas.
Para Operation(PATCH_OPERATION_INDEX): A operação Add só pode criar um objeto filho de um nó existente (matriz ou objeto) e não pode criar um caminho recursivamente, nenhum caminho encontrado além de: PATH. Os caminhos filho podem ser adicionados a um tipo de objeto ou nó de matriz. Além disso, para criar no filho, n-1o filho deve estar presente.
Para Operation(PATCH_OPERATION_INDEX): A operação dada só pode criar um objeto filho de um nó já existente (matriz ou objeto) e não pode criar um caminho de forma recursiva, não foi encontrado nenhum caminho além de: PATH. Os caminhos filho podem ser adicionados a um tipo de objeto ou nó de matriz. Além disso, para criar no filho, n-1o filho deve estar presente.

Próximo passo