Azure Functions is a useful product that effectively lets you run a small piece of server logic based on a wide variety of triggers. It’s an amazing tool for a microservices based architecture. And making Azure Functions even more powerful is its ability to easily connect to your Cosmos DB database to read and write documents.
In 2022, I wrote an article on connecting the dots between Azure Functions and Cosmos DB, but there’s been changes in Azure Functions since then that made the article obsolete. Specifically, they have moved to something called Isolated Worker functions. With this new foundation, the attributes required to work with Cosmos DB has changed.
Reading from Cosmos DB
[Function("TestFunction")]
public async Task<object?> Run([CosmosDBInput("databaseName", "containerName", Connection = "CosmosDbConnectionString")] IEnumerable<MyDocument> documents)
{
foreach (var doc in documents)
{
// do work on your documents
}
}
To read from Cosmos DB, you need to use theCosmosDBInput
attribute as an input parameter to your Azure Function. Once you’ve set this up with the correct database name, container name, and connection string, your Function will automatically read your database. In the above example, it’s fetching all the documents in that container, but there are numerous other ways to read data using attribute. You can view the official docs here to see the full capabilities. Meanwhile, I want to a couple of my favourites.
Get a reference to the container client for fully custom queries:
[CosmosDBInput("databaseName", "containerName", Connection = "CosmosDbConnectionString")] Container cosmosDbContainer
...
var item = await cosmosDbContainer.ReadItemAsync<T>(id, new PartitionKey(id));
Get a specific item based on a specific ID:
[CosmosDBInput(
"databaseName",
"containerName",
Connection = "CosmosDBConnection",
Id = "{ToDoItemId}",
PartitionKey = "{ToDoItemPartitionKeyValue}")] ToDoItem toDoItem)
And there you have it! An easy way to read cosmos DB documents from an Azure Function. Remember to read to full docs for Cosmos DB input binding here.
Writing to Cosmos DB
[Function("TestFunction")]
[CosmosDBOutput("databaseName", "containerName", Connection = "CosmosDbConnectionString", CreateIfNotExists = false)]
public async Task<object?> Run(...)
{
return new MyDocument()
}
In order to write to Cosmos DB from an Azure Function, you need to use theCosmosDBOutput
attribute. Notice that this isn’t an attribute on an input parameter, but rather it’s an attribute on the Run
method itself.
For this output binding, the return result will be upserted to your Cosmos DB. Read that again, it will be upserted. If the document’s ID doesn’t in your Cosmos DB, then it will be inserted as a new document. If the ID of the object already exists, then it will overwrite the existing document! Full docs can be viewed here.
So that’s all there is to it. use CosmosDBOutput
for inserts and updates to your database and use CosmosDBInput
to read data. I’m a big fan of Azure Functions, so I hope you find this useful to start or continue your microservices journey.