Introduction to Cosmos DB Bindings
Azure Functions provide powerful input and output bindings for Azure Cosmos DB, enabling seamless interaction with your NoSQL data from serverless code. These bindings abstract away the complexities of the Cosmos DB SDK, allowing you to focus on your business logic.
You can use these bindings for:
- Reading documents from a Cosmos DB container as input to your function.
- Writing documents to a Cosmos DB container as output from your function.
- Triggering functions when changes occur in a Cosmos DB container (using the Cosmos DB trigger).
Input Bindings
Input bindings allow you to read data from Cosmos DB and pass it as parameters to your function. This is useful for retrieving configuration, user data, or any other relevant information needed for your function's execution.
Document Input
Retrieve a single document by its ID or query a collection using SQL.
Example (C#):
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.Documents.Client;
using System.Threading.Tasks;
public static class GetCosmosDoc
{
[FunctionName("GetCosmosDoc")]
public static async Task Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "items/{id}")] HttpRequestMessage req,
[CosmosDB(
databaseName: "ToDoList",
collectionName: "Items",
ConnectionStringSetting = "CosmosDBConnection",
Id = "{id}",
PartitionKey = "{id}" // Required if partition key is different from ID
)] dynamic document)
{
if (document == null)
{
// Handle item not found
return req.CreateResponse(HttpStatusCode.NotFound);
}
// Process the document
return req.CreateResponse(HttpStatusCode.OK, document);
}
}
Collection Input
Retrieve multiple documents that match a SQL query.
Example (JavaScript):
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
// Assuming 'todos' is bound as a collection input from Cosmos DB
// using a SQL query like "SELECT * FROM c WHERE c.isComplete = false"
const incompleteTodos = context.bindings.todos;
if (incompleteTodos) {
context.res = {
body: incompleteTodos
};
} else {
context.res = {
status: 404,
body: "No incomplete todos found."
};
}
};
The input binding configuration in function.json would look like this:
{
"scriptFile": "index.js",
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "cosmosDB",
"name": "todos",
"direction": "in",
"databaseName": "ToDoList",
"collectionName": "Items",
"connectionStringSetting": "CosmosDBConnection",
"sqlQuery": "SELECT * FROM c WHERE c.isComplete = false"
}
]
}
Output Bindings
Output bindings allow you to write data to Cosmos DB from your function. This is typically used to store results, log events, or update records.
Example (Node.js):
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
const newItem = req.body;
// The 'newDocument' output binding will write the newItem to Cosmos DB
context.bindings.newDocument = newItem;
context.res = {
status: 201,
body: "Item created successfully"
};
};
The output binding configuration in function.json:
{
"scriptFile": "index.js",
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "cosmosDB",
"name": "newDocument",
"direction": "out",
"databaseName": "ToDoList",
"collectionName": "Items",
"connectionStringSetting": "CosmosDBConnection"
}
]
}
Cosmos DB Trigger
The Cosmos DB trigger allows your function to be executed automatically in response to changes in a Cosmos DB container. It leverages the Change Feed API to monitor for inserts and updates.
Example (Python):
import logging
import azure.functions as func
def main(event: func.EventGridEvent):
logging.info('Python EventGrid trigger function received a Cosmos DB change event.')
logging.info('Event Type: %s', event.event_type)
logging.info('Event Body: %s', event.get_json())
# The event body contains the changed document(s)
for record in event.get_json():
logging.info(f"Processing document ID: {record['Document']['id']}")
# Your logic to process the changed document goes here
The trigger configuration in function.json:
{
"scriptFile": "__init__.py",
"bindings": [
{
"type": "cosmosDBTrigger",
"name": "event",
"direction": "in",
"databaseName": "ToDoList",
"collectionName": "Items",
"connectionStringSetting": "CosmosDBConnection",
"createLeaseCollectionIfNotExists": true
}
]
}
Configuration and Settings
Cosmos DB bindings rely on connection strings defined in your Azure Functions application settings. Typically, this is named CosmosDBConnection.
In your local.settings.json file (for local development):
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"CosmosDBConnection": "AccountEndpoint=https://YOUR_COSMOS_DB_ACCOUNT.documents.azure.com:443/;AccountKey=YOUR_ACCOUNT_KEY;"
}
}
In your Azure Functions app settings in the Azure portal, ensure you have a similar setting for CosmosDBConnection.
Key Binding Properties
| Property | Description | Required |
|---|---|---|
| databaseName | The name of the Cosmos DB database. | Yes |
| collectionName | The name of the Cosmos DB container (collection). | Yes |
| connectionStringSetting | The name of the application setting that contains the Cosmos DB connection string. | Yes |
| Id | (Input only) The ID of the document to retrieve. Can be a binding expression. | No |
| PartitionKey | (Input only) The partition key value for the document. Required if the partition key is different from the document ID. Can be a binding expression. | No |
| sqlQuery | (Input only) A SQL query to retrieve documents from the collection. | No |
| createLeaseCollectionIfNotExists | (Trigger only) If true, automatically creates the lease collection if it doesn't exist. | No |
Best Practices
- Use Connection Strings Securely: Store your Cosmos DB connection strings in application settings, not directly in your code.
- Handle Errors Gracefully: Implement robust error handling for cases where documents are not found or writes fail.
- Optimize Queries: For input bindings, ensure your SQL queries are efficient and leverage appropriate indexing.
- Partition Key Management: Understand and correctly specify partition keys, especially for large collections or when retrieving single documents.
- Trigger Lease Management: For triggers, ensure the lease collection is properly configured and managed.