How to execute server-side Cosmos DB Patch using the JavaScript API?

Viewed 65

Trying to implement server-side patching, following the guidance here: https://docs.microsoft.com/en-us/azure/cosmos-db/partial-document-update-getting-started?tabs=dotnet#support-for-server-side-programming

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

The code references several functions and objects that appear built-in: validateDocumentLink, validateOptionsAndCallback, and collectionObjRaw

The source for these is here https://azure.github.io/azure-cosmosdb-js-server/DocDbWrapperScript.js.html, but my understanding was they should be accessible from server-side script.

When I run the sample code in a new stored procedure, however, these functions and objects are all null.

What am I missing?

Update Attempting to implement the solution suggested by @sajeetharan below (and fixing a couple of unclosed parentheses in that example that were causing it to fail to compile), we came up with this simple test function:

function test() {
    var doc = {
        "id": "exampleDoc",
        "field1": {
            "field2": 10,
            "field3": 20
        }
    };
    var isAccepted = __.createDocument(__.getSelfLink(), doc, (err, doc) => {
    if (err) throw err;
    var patchSpec = [
        {"op": "add", "path": "/field1/field2", "value": 20},
        {"op": "remove", "path": "/field1/field3"}
    ];

    var patchAccepted = __.patchDocument(doc._self, patchSpec, (err, doc) => {
            if (err) throw err;
            else {
                getContext().getResponse().setBody(docPatched);
            }
    });

        if(!patchAccepted) throw new Error("patch was't accepted")
    });

    if(!isAccepted) throw new Error("create wasn't accepted")
}

Which fails with:

Message: {"Errors":["Encountered exception while executing function. Exception = ReferenceError: 'validateDocumentLink' is not defined\r\nStack trace: ReferenceError: 'validateDocumentLink' is not defined\n at collection.patchDocument (script.js:23:5)\n at Anonymous function (script.js:18:10)\n at Anonymous function (script.js:689:29)"]}

The underlying issue, both for our own code and this new test function, is a lack of scope to what we understand should be built-in functions of the Cosmos DB JavaScript API.

Are we missing a necessary initialization step here? Is this code that can't run in a stored procedure, and should be in a trigger or a UDF? What else could be wrong?

(I should add we're testing this using the Execute function at https://cosmos.azure.com/ - in case the bug is an artefact of that rather shaky UI.)

1 Answers

You can use the sample code below to perform the same,

function () {
   var doc = {
      "id": "exampleDoc",
      "field1": {
         "field2": 10,
         "field3": 20
      }
   };
   var isAccepted = __.createDocument(__.getSelfLink(), doc, (err, doc) => {
         if (err) throw err;
         var patchSpec = [
            {"op": "add", "path": "/field1/field2", "value": 20},
            {"op": "remove", "path": "/field1/field3"}
         ];
         isAccepted = __.patchDocument(doc._self, patchSpec, (err, doc) => {
               if (err) throw err;
               else {
                  getContext().getResponse().setBody(docPatched);
               }
            }
         }
         if(!isAccepted) throw new Error("patch was't accepted")
      }
   }
   if(!isAccepted) throw new Error("create wasn't accepted")
}
 
// Example 2: Patch document with patch spec specified as object<br/>.
function () {
   var docLink = "dbs/db1/colls/coll1/docs/doc1"
   var patchSpec = {
      "isUpsert": true,
      "setOnCreate": "{\"id\":\"doc1\"}",
      "operations": [{
         "op": "add",
         "path": "/foo",
         "value": 10
      }]
   }
   var isAccepted = __.patchDocument(docLink, patchSpec, (err, doc) => {
         if (err) throw err;
         else {
            getContext().getResponse().setBody(docPatched);
         }
      }
   }
   if(!isAccepted) throw new Error("patch was't accepted")
}

Thanks for providing the feedback, we will update the sample given on the docs page.

Related