4
votes

I have a stored procedure on a partitioned collection (in Azure Cosmos DB). It ought to update a given document or create it if it does not exist. Since the collection is partitioned I need the partition key in whose scope the stored procedure is being executed to create the document.

How can I get the partition key related to a request from within a stored procedure?


Based on the documentation (Common Azure Cosmos DB REST request headers) the request header parameter for the partition key is: x-ms-documentdb-partitionkey.

The documentation for the Server-Side JavaScript SDK regarding the Request class says:

The Request object represents the request message that was sent to the server. This includes information about HTTP headers and the body of the HTTP request sent to the server. For triggers, the request represents the operation that is executing when the trigger is run. For example, if the trigger is being run ("triggered") on the creation of a document, then the request body contains the JSON body of the document to be created. This can be accessed through the request object and (as JSON) can be natively consumed in JavaScript. For stored procedures, the request contains information about the request sent to execute the stored procedure.

I've tried to get the partition key from the HTTP request's header as follows:

getContext().getRequest().getValue('x-ms-documentdb-partitionkey')  //returns: "Unable to get property 'value' of undefined or null reference"
getContext().getRequest()['x-ms-documentdb-partitionkey']   //returns: "undefined"

Example code:

function createOrUpdateSproc(documentId) {
    let isAccepted = __.queryDocuments(__.getSelfLink(),
        `SELECT * FROM c WHERE c.id = "${documentId}"`,
        function (err, feed, options) {
            if (err) throw err;

            // Check the feed and if empty, create document; otherwise take first element from feed.
            if (!feed || !feed.length) {
                createDocument();
            } else {
                replaceDocument(undefined, feed[0]);
            }
        }
    );
    if (!isAccepted) throw new Error('Querying refused.');

    function createDocument() {
        let documentBody = {
            id: documentId,
            partitionKey: __.request['x-ms-documentdb-partitionkey'],  // Based on documentation.
            counter: 1
        };

        let isAccepted = __.createDocument(__.getSelfLink(),
            documentBody,
            { disableAutomaticIdGeneration: true },
            replaceDocument);
        if (!isAccepted) throw new Error('Creating refused.');
    }

    function replaceDocument(err, document, createOptions) {
        ...
    }
}
1

1 Answers

0
votes

I used the js code in sp to print the structure of getRequest().

var collection = getContext().getCollection();
var r = getContext().getRequest();
for(var i in r){
   console.log(i+"-------");
   console.log(r[i]+"++++");
}

But I got the below structure.

"getx-ms-documentdb-script-enable-logging-------function () {\r\n                    return getValueInternal(propName);\r\n                }++++getValue-------function (propertyName) {\r\n                    return getValueInternal(propertyName);\r\n                }++++"

It does not match the properties which is mentioned in the Js API document.

Maybe you could use Azure Http Trigger Function as a workaround to implement the same logical business. Just pass the partition key to the Function as parameters then do the query ,create or update stuffs with cosmos db sdk in the Function method. The trigger function can be called from applications,users or any other client sides.