Sync two CosmosDB collections with an Azure Function
Tags: azure, cosmosdb, function, csharp
Published: 2020-10-17 11:35:40

## Table of Contents
1 [Objective](#objective )  
2 [Cosmos DB](#"cosmosdb)  
3 [Azure Function](#azurefunction)  
4 [Result](#result)  

## 1 Objective <a id="objective "></a>

Data in the Cosmos DB has to be optimized for querying.
Therefore some best practices have to be considered.

[Best practices for Azure Cosmos DB: Data modeling, Partitioning and RUs](https://azure.microsoft.com/en-us/resources/videos/build-2019-best-practices-for-azure-cosmos-db-data-modeling-partitioning-and-rus/ "Best practices for Azure Cosmos DB: Data modeling, Partitioning and RUs")

[Performance tips for Azure Cosmos DB and .NET SDK v2](https://docs.microsoft.com/en-us/azure/cosmos-db/performance-tips "Performance tips for Azure Cosmos DB and .NET SDK v2")

An [Azure Function](https://docs.microsoft.com/en-us/azure/azure-functions/ "Azure Functions documentation") will be used to automatically copy data from one Cosmos DB collection to another collection with a different [PartitionKey](https://docs.microsoft.com/en-us/azure/cosmos-db/partitioning-overview "Partitioning in Azure Cosmos DB").

## 2 Cosmos DB<a id="cosmosdb"></a>

The Cosmos DB collection is used to store customer data:

_Customer_:
```json
{
    "id":"000001",
    "CustomerId":"000001",
    "EmailAddress":"user1@lorem.com",
    "Country": "Germany"
}
```

The Cosmos DB database has two collections for storing customer data:


### 2.1 Customer
One collection is optimized for query data by EmailAddress with PartitionKey _/EmailAddress_.
This is also the primary collection for storing the received data.

![cosmosdb-customer.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1602918604367/n9g_FIW-k.png)

### 2.2 Customer-by-Country

This collection is optimized for query data by Country with PartitionKey _/Country_.

![cosmosdb-customer-by-country.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1602918612077/d_9fPdHk-.png)

## 3 Azure Function<a id="azurefunction"></a>

The Azure Functions has a _CosmosDBTrigger_. Every time a customer is created or updated in the collection *customer*, the Function will be triggered.  

**Attention**: The Function will not be trigger if a customer was deleted!

The trigger is configured with *customer* collection.  

The outbound binding uses an [IAsyncCollector](https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-class-library#binding-to-method-return-value "Binding to method return value") to add the received data to the collection *customer_by_country*.

_FunctionCode_:
```csharp
public static class SyncCosmosDb
{
    [FunctionName(nameof(Sync))]
    public static void Sync(
        [CosmosDBTrigger(
                databaseName: "evaluation",
                collectionName: "customer",
                ConnectionStringSetting = "cosmos-mm-eval",
                LeaseCollectionName = "leases",
                CreateLeaseCollectionIfNotExists=true
            )]IReadOnlyList<dynamic> input,
        [CosmosDB(
                databaseName: "evaluation",
                collectionName: "customer-by-country",
                ConnectionStringSetting = "cosmos-mm-eval")] IAsyncCollector< dynamic> output,
        ILogger log)

    {

        foreach (var item in input)
        {
            output.AddAsync(item);
        }
    }
}
```

The Cosmos DB connection string  has to be configured in _local.settings.json_:
```json
{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "AzureWebJobsDashboard": "UseDevelopmentStorage=true",
    "cosmos-mm-eval": "secret",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet"
  }
}
```
The complete solution can be found in my [GitHub repository](https://github.com/MarkusMeyer13/CosmosDBSyncFunction "https://github.com/MarkusMeyer13/CosmosDBSyncFunction").

## 4 Result <a id="result"></a>

Both collections contain the same data:

_Collection customer_:
![cosmosdb-customer-items.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1602925750162/QvYAD7zGI.png)


_Collection customer-by-country_:
![cosmosdb-customer-by-country-items.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1602926016043/Z3F4_oewm.png)