Azure Functions: Cosmos DB Input Bindings

Introduction to Cosmos DB Input Bindings

Azure Functions can integrate with Azure Cosmos DB to read data efficiently using input bindings. This allows you to retrieve documents from a Cosmos DB container directly within your function's execution context, simplifying data access logic.

Input bindings are declared in your function's function.json file (for C#, JavaScript, and Python) or through attributes (for C#). When the function is triggered, the runtime automatically fetches the data based on the binding configuration and makes it available as a parameter in your function code.

Configuring a Cosmos DB Input Binding

To configure a Cosmos DB input binding, you need to define it in your function.json file. Here's a typical configuration:

function.json
{
    "scriptFile": "run.csx",
    "bindings": [
        {
            "name": "inputDocument",
            "type": "cosmosDB",
            "direction": "in",
            "databaseName": "MyDatabase",
            "collectionName": "MyCollection",
            "connectionStringSetting": "CosmosDBConnectionString",
            "id": "{Query.documentId}"
        },
        {
            "name": "outputBlob",
            "type": "blob",
            "direction": "out",
            "path": "output/{Query.documentId}.txt",
            "connection": "AzureWebJobsStorage"
        }
    ]
}

Key Properties:

Using Binding Expressions

Binding expressions provide a powerful way to dynamically specify values for binding properties. You can refer to properties from the trigger input, other bindings, or HTTP request properties.

For example, to retrieve a document based on its partition key:

function.json (with Partition Key)
{
    "scriptFile": "run.csx",
    "bindings": [
        {
            "name": "inputDocument",
            "type": "cosmosDB",
            "direction": "in",
            "databaseName": "MyDatabase",
            "collectionName": "MyCollection",
            "connectionStringSetting": "CosmosDBConnectionString",
            "id": "{Query.docId}",
            "partitionKey": "{Query.partitionKey}"
        }
    ]
}

Code Examples

C# Example

When using C#, you can define bindings using attributes in your function class.

C# Function
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using System.Net.Http;
using System.Threading.Tasks;

public static class GetCosmosDoc
{
    [FunctionName("GetCosmosDoc")]
    public static async Task<HttpResponseMessage> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = "item/{id}/{partitionKey}")] HttpRequestMessage req,
        [CosmosDB(
            databaseName: "MyDatabase",
            collectionName: "MyCollection",
            ConnectionStringSetting = "CosmosDBConnectionString",
            Id = "{id}",
            PartitionKey = "{partitionKey}")] dynamic inputDocument)
    {
        if (inputDocument == null)
        {
            return req.CreateErrorResponse(System.Net.HttpStatusCode.NotFound, "Document not found.");
        }

        // Process the inputDocument
        return req.CreateResponse(System.Net.HttpStatusCode.OK, inputDocument);
    }
}

JavaScript Example

In JavaScript, bindings are defined in function.json, and the data is accessed via the context.bindings object.

function.json (JavaScript)
{
    "scriptFile": "index.js",
    "bindings": [
        {
            "name": "req",
            "type": "httpTrigger",
            "direction": "in",
            "methods": ["get"],
            "route": "item/{id}/{partitionKey}"
        },
        {
            "name": "inputDocument",
            "type": "cosmosDB",
            "direction": "in",
            "databaseName": "MyDatabase",
            "collectionName": "MyCollection",
            "connectionStringSetting": "CosmosDBConnectionString",
            "id": "{id}",
            "partitionKey": "{partitionKey}"
        },
        {
            "name": "res",
            "type": "http",
            "direction": "out"
        }
    ]
}
index.js
module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');

    const inputDocument = context.bindings.inputDocument;

    if (inputDocument) {
        context.res = {
            status: 200,
            body: inputDocument
        };
    } else {
        context.res = {
            status: 404,
            body: "Document not found."
        };
    }
};

Data Types and Behavior

The data retrieved by the Cosmos DB input binding can be accessed as:

If no document is found with the specified ID, the binding parameter will be null (or its equivalent in other languages).

Important Considerations

Note: For efficient retrieval of multiple documents or querying, consider using the Cosmos DB output binding to execute queries and then processing the results. Input bindings are best suited for fetching a single, known document by its ID.
Tip: Ensure your CosmosDBConnectionString setting in your Azure Functions app configuration is correctly set and points to your Cosmos DB account.

When using partition keys, ensure that the partition key value provided in the binding expression matches the actual partition key of the document you intend to retrieve. Mismatched partition keys will result in the document not being found.