Processing a Single Azure Cosmos DB Document at a Time With Azure Functions

This is the fifth part in a series of articles.

In previous parts of this series the Azure Function code receives one or more Cosmos DB documents as part of the trigger.

The Azure Functions Cosmos DB trigger uses the change feed from Azure Cosmos to determine when to trigger the function and also what changes to send to the function invocation. If there is only a single updated (or inserted) document then the function will be called and the single document passed to it.

Notice in the following code that the document(s) that need processing are contained in the IReadOnlyList<Document> modifiedDriver collection:

[FunctionName("PizzaDriverLocationUpdated")]
public static async Task Run([CosmosDBTrigger(
    databaseName: "pizza",
    collectionName: "driver",
    ConnectionStringSetting = "pizzaConnection")] IReadOnlyList<Document> modifiedDrivers,            
    ILogger log)
{
    if (modifiedDrivers != null)
    {
        log.LogInformation($"Total modified drivers: {modifiedDrivers.Count}");

        foreach (var modifiedDriver in modifiedDrivers)
        {
            var driverName = modifiedDriver.GetPropertyValue<string>("Name");
            var driverLat = modifiedDriver.GetPropertyValue<double>("Latitude");
            var driverLong = modifiedDriver.GetPropertyValue<double>("Longitude");

            log.LogInformation($"Driver {modifiedDriver.Id} {driverName} was updated (lat,long) {driverLat}, {driverLong}");                    
        }
    }
}

The preceding code just outputs what documents changed to the log/console.

The reason that the foreach loop is required is that the function may receive multiple documents from the change feed.

If you only want to work with a single document per invocation of the function you can restrict the number of documents. To do this the MaxItemsPerInvocation property of the trigger attribute can be set as the following code demonstrates:

[FunctionName("PizzaDriverLocationUpdated")]
public static async Task Run([CosmosDBTrigger(
    databaseName: "pizza",
    collectionName: "driver",
    MaxItemsPerInvocation = 1,
    ConnectionStringSetting = "pizzaConnection")] IReadOnlyList<Document> modifiedDrivers,            
    ILogger log)
{
    if (modifiedDrivers != null)
    {
        log.LogInformation($"Total modified drivers: {modifiedDrivers.Count}");

        foreach (var modifiedDriver in modifiedDrivers)
        {
            var driverName = modifiedDriver.GetPropertyValue<string>("Name");
            var driverLat = modifiedDriver.GetPropertyValue<double>("Latitude");
            var driverLong = modifiedDriver.GetPropertyValue<double>("Longitude");

            log.LogInformation($"Driver {modifiedDriver.Id} {driverName} was updated (lat,long) {driverLat}, {driverLong}");                    
        }
    }
}

Now there will only be one document in the collection, so the function can be simplified to the following (removing the foreach loop):

[FunctionName("PizzaDriverLocationUpdated")]
public static async Task Run([CosmosDBTrigger(
    databaseName: "pizza",
    collectionName: "driver",
    MaxItemsPerInvocation = 1,
    ConnectionStringSetting = "pizzaConnection")] IReadOnlyList<Document> modifiedDrivers,
    ILogger log)
{
    if (modifiedDrivers != null && modifiedDrivers.Any())
    {
        var modifiedDriver = modifiedDrivers[0];

        var driverName = modifiedDriver.GetPropertyValue<string>("Name");
        var driverLat = modifiedDriver.GetPropertyValue<double>("Latitude");
        var driverLong = modifiedDriver.GetPropertyValue<double>("Longitude");

        log.LogInformation($"Driver {modifiedDriver.Id} {driverName} was updated (lat,long) {driverLat}, {driverLong}");                
    }
}

Now if 2 updates are made to the database, the function will execute twice, once per changed document:

Executing 'PizzaDriverLocationUpdated' (Reason='New changes on collection driver at 2019-05-28T05:42:25.2143459Z', Id=06d1e318-ab26-4f9b-ac94-3c95fba2dc5c)
Driver 1 Amrit was updated (lat,long) 31.2, 300.3
Executed 'PizzaDriverLocationUpdated' (Succeeded, Id=06d1e318-ab26-4f9b-ac94-3c95fba2dc5c)
Executing 'PizzaDriverLocationUpdated' (Reason='New changes on collection driver at 2019-05-28T05:42:25.5350736Z', Id=34629f4a-66f4-4bbc-85d6-8c3d8c17ee62)
Driver 2 Sarah was updated (lat,long) 222.1, 31.2
Executed 'PizzaDriverLocationUpdated' (Succeeded, Id=34629f4a-66f4-4bbc-85d6-8c3d8c17ee62)

In the next part of this series we’ll look at how to execute multiple different functions when a document changes.

If you want to fill in the gaps in your C# knowledge be sure to check out my C# Tips and Traps training course from Pluralsight – get started with a free trial.

SHARE:

Add comment

Loading