Cosmos DB (DocumentDB) Bindings
Retrieve a single document by ID
The Cosmos DB binding can automatically retrieve a document from Cosmos DB and bind it to a parameter. This example uses an object
. The Cosmos DB binding uses a binding expression ({id}
) to look up a document from Cosmos DB using the id
value from the HttpTrigger route.
[FunctionName("CosmosDBSample")]
public static HttpResponseMessage Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "foo/{id}")] HttpRequestMessage req,
[DocumentDB("test", "test", ConnectionStringSetting = "CosmosDB", Id = "{id}")] object document)
{
if (document == null)
{
return req.CreateResponse(HttpStatusCode.NotFound);
}
else
{
return req.CreateResponse(HttpStatusCode.OK, document);
}
}
Retrieve a list of documents
The Cosmos DB binding can automatically retrieve a list of documents from Cosmos DB and bind it to a parameter. The sqlQuery
property of the binding is used to specify a query to use to retrieve the documents. This example demonstrates how to select the five most recent documents from the collection as determined by the _ts
timestamp property.
[FunctionName("CosmosDBSample")]
public static HttpResponseMessage Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequestMessage req,
[DocumentDB("test", "test", ConnectionStringSetting = "CosmosDB", sqlQuery = "SELECT top 2 * FROM c order by c._ts desc")] IEnumerable<object> documents)
{
return req.CreateResponse(HttpStatusCode.OK, documents);
}
Save multiple documents to a collection
The IAsyncCollector
lets you save multiple documents within one execution of your Function.
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
public class MyClass
{
public string id { get; set; }
public string name { get; set; }
}
[FunctionName("CosmosDbSample")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]MyClass[] classes,
TraceWriter log,
[DocumentDB("ToDoList", "Items", ConnectionStringSetting = "CosmosDB")] IAsyncCollector<MyClass> documentsToStore)
{
log.Info($"Detected {classes.Length} incoming documents");
foreach (MyClass aClass in classes)
{
await documentsToStore.AddAsync(aClass);
}
return new HttpResponseMessage(HttpStatusCode.Created);
}
Trigger a Function based on changes in Cosmos DB
You can trigger a Function based on changes in your Cosmos DB collections. In this sample we are sending the changes to a second collection using the IAsyncCollection
explained in this other recipe. You could process or work with the documents before sending it to the second collection.
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
[FunctionName("CosmosDbSample")]
public static async Task Run(
[CosmosDBTrigger("ToDoList","Items", ConnectionStringSetting = "CosmosDB")] IReadOnlyList<Document> documents,
TraceWriter log,
[DocumentDB("ToDoList", "Migration", ConnectionStringSetting = "CosmosDB", CreateIfNotExists = true)] IAsyncCollector<Document> documentsToStore)
{
foreach (var doc in documents)
{
log.Info($"Processing document with Id {doc.Id}");
// work with the document, process or create a new one
await documentsToStore.AddAsync(doc);
}
}
Using DocumentClient
If you have complex queries that are not supported by id
and sqlQuery
of the Cosmos DB input binding, you can use the DocumentClient
directly.
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.Documents.Linq;
[FunctionName("CosmosDBSample")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequestMessage req,
[DocumentDB("test", "test", ConnectionStringSetting = "CosmosDB")] DocumentClient client,
int minAge,
TraceWriter log)
{
Uri collectionUri = UriFactory.CreateDocumentCollectionUri("mydb", "mycollection");
IDocumentQuery<Person> query = client.CreateDocumentQuery<Person>(collectionUri)
.Where(p => p.Age >= minAge)
.AsDocumentQuery();
while (query.HasMoreResults)
{
foreach (Person result in await query.ExecuteNextAsync())
{
log.Info(result.Age.ToString());
}
}
}
Customize a DocumentClient and reuse it between executions
You can create your own DocumentClient
and customize it for your needs, while maintaining a single shared instance for all the Function's executions. The single instance is ensured by the use of the static
keyword when declaring the DocumentClient
.
using System;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
private static DocumentClient client = GetCustomClient();
private static DocumentClient GetCustomClient()
{
DocumentClient customClient = new DocumentClient(
new Uri(ConfigurationManager.AppSettings["CosmosDBAccountEndpoint"]),
ConfigurationManager.AppSettings["CosmosDBAccountKey"],
new ConnectionPolicy
{
ConnectionMode = ConnectionMode.Direct,
ConnectionProtocol = Protocol.Tcp,
// Customize retry options for Throttled requests
RetryOptions = new RetryOptions()
{
MaxRetryAttemptsOnThrottledRequests = 10,
MaxRetryWaitTimeInSeconds = 30
}
});
// Customize PreferredLocations
customClient.ConnectionPolicy.PreferredLocations.Add(LocationNames.CentralUS);
customClient.ConnectionPolicy.PreferredLocations.Add(LocationNames.NorthEurope);
return customClient;
}
[FunctionName("CosmosDbSample")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "foo/{id}")] HttpRequestMessage req,
string id,
TraceWriter log)
{
Uri documentUri = UriFactory.CreateDocumentUri("ToDoList", "Items", id);
Document doc = await client.ReadDocumentAsync(documentUri);
if (doc == null)
{
return req.CreateResponse(HttpStatusCode.NotFound);
}
return req.CreateResponse(HttpStatusCode.OK, doc);
}
Takeaways
- The
static
keyword acts as a Singleton, maintaining the same instance for all the executions within a Function's instance. - You can customize your
DocumentClient
with your ownConnectionPolicy
requirements.