Search code examples
azure-cosmosdbjava-stored-procedures

Aggregate function with JavaScript query API in Azure Cosmos DB


I'm working with CosmosDB stored procedure and user defined function.

I have to write a stored procedure that return the max of four fields of a collection.

In Sql I write:

    SQL MAX(A) AS MASSIMOA, MAX(B) AS MASSIMOB, .... FROM COLLECTION

I don't know how to write it using javascript into a stored procedure. Can anyone help me? Simone

Sample Data :

    {
        "messageUID": "EBBBrain-10608941722019-05-31T16:58:13+02:00",
        "deviceId": "EBBBrain-1060894172",
        "dateTimeDevice": "2019-05-31T14:58:13",
        "messageId": 38,
        "release": 104,
        "VIn": 23342,
        "VOut": 20513,
        "AIn": 53,
        "AOut": 40,
        "CosPhi": 42,
        "W": 53,
        "Var": 112,
        "VA": 124,
        "WhCnt": 361587,
        "VarhCnt": 749631,
        "TimeSlot": 0,
        "MeterTS": "2019-05-31 16:58:14",
        "Sampling": 60,
        "Wh": 3423,
        "Varh": 7105,
        "WSaved": 0,
        "EventProcessedUtcTime": "2019-05-31T14:58:15.3238226Z",
        "PartitionId": 1,
        "EventEnqueuedUtcTime": "2019-05-31T14:58:15.285Z",
        "IoTHub": {
            "MessageId": null,
            "CorrelationId": null,
            "ConnectionDeviceId": "Device",
            "ConnectionDeviceGenerationId": "636909297614425839",
            "EnqueuedTime": "2019-05-31T14:58:15.292Z",
            "StreamId": null
        },
        "id": "EBBBrain-1060894172",
        "_rid": "dEkOAONukREBAAAAAAAAAA==",
        "_self": "dbs/dEkOAA==/colls/dEkOAONukRE=/docs/dEkOAONukREBAAAAAAAAAA==/",
        "_etag": "\"2400a1a2-0000-0c00-0000-5cf1415c0000\"",
        "_attachments": "attachments/",
        "_ts": 1559314780
    }

and the sql statement based on the sample is :

    SELECT max(r.VIn) as maxNum FROM root r

Solution

  • Cosmos db supports native aggregate function as below:

    enter image description here

    So, you could use MAX in normal sql.

    'SELECT max(r.num) as maxNum FROM root r'
    

    In stored procedure, no more difference.

    // SAMPLE STORED PROCEDURE
    function sample() {
        var collection = getContext().getCollection();
    
        var isAccepted = collection.queryDocuments(
            collection.getSelfLink(),
            'SELECT max(r.num) as maxNum FROM root r',
        function (err, feed, options) {
            if (err) throw err;
    
            if (!feed || !feed.length) {
                var response = getContext().getResponse();
                response.setBody('no docs found');
            }
            else {
                var response = getContext().getResponse();
                response.setBody(feed);
            }
        });
    
        if (!isAccepted) throw new Error('The query was not accepted by the server.');
    }
    

    Output:

    enter image description here


    Update Answer:

    The issue is resulted from the size of data. The aggregate function in the cosmos db will across all the data if you do not set any filter in the query sql. That's a such huge workload and can't be finished by stored procedure directly. Stored procedure has execute limitation, please refer to this link:

    enter image description here

    So, my suggestion is using continuation token to doing the paging completion. You could set the maxItemCount param in the code,like below:

    client.QueryDocuments(collection_link, query, {'maxItemCount':100})
    

    Then use continuation token to get the max number of single page. Finally, compare those numbers to get the maximum. About usage of continuation token,you could refer to this thread: Document DB 5 secs stored procedure execution limit