共用方式為


開始使用 Azure Cosmos DB 部分文件更新

適用於:NoSQL

本文提供的範例說明如何在 .NET、Java、Node SDK 中使用部分文件更新。 文中亦描述您可能會遇到的常見錯誤。

本文連結至下列案例的程式碼範例:

  • 執行單一修補作業
  • 結合多個修補作業
  • 使用以篩選述詞為基礎的條件式修補程式語法
  • 在交易中執行修補作業

必要條件

Azure Cosmos DB .NET v3 SDK 從 3.23.0 版起支援部分文件更新 (修補 API)。 您可以從 NuGet 資源庫下載此 SDK。

注意

您可以在 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) 無法使用修補作業來修改。 如需詳細資訊,請參閱部分文件更新常見問題集
修補作業數目不可超過 10 個。 單一修補規格中最多只能新增 10 個修補作業。 如需詳細資訊,請參閱部分文件更新常見問題集
作業 (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 個子系必須存在。

下一步