1
votes

I have 2 collections in CosmosDB, Stocks and StockPrices.

StockPrices collection holds all historical prices, and is constantly updated.

I want to create Azure Function that listens to StockPrices updates (CosmosDBTrigger) and then does the following for each Document passed by the trigger:

  1. Find stock with matching ticker in Stocks collection
  2. Update stock price in Stocks collection

I can't do this with CosmosDB input binding, as CosmosDBTrigger passes a List (binding only works when trigger passes a single item).

The only way I see this working is if I foreach on CosmosDBTrigger List, and access CosmosDB from my function body and perform steps 1 and 2 above.

Question: How do I access CosmosDB from within my function?

2

2 Answers

1
votes

One of the CosmosDB binding forms is to get a DocumentClient instance, which provides the full range of operations on the container. This way, you should be able to combine the change feed trigger and the item manipulation into the same function, like:

[FunctionName("ProcessStockChanges")]
public async Task Run(
    [CosmosDBTrigger(/* Trigger params */)] IReadOnlyList<Document> changedItems,
    [CosmosDB(/* Client params */)] DocumentClient client,
    ILogger log)
{
    // Read changedItems, 
    // Create/read/update/delete with client
}

It's also possible with .NET Core to use dependency injection to provide a full-fledged custom service/repository class to your function instance to interface to Cosmos. This is my preferred approach, because I can do validation, control serialization, etc with the latest version of the Cosmos SDK.

You may have done so intentionally, but just mentioning to consider combining your data into a single container partitioned by, for example, a combination of record type (Stock/StockPrice) and identifier. This simplifies things and can be more cost/resource efficient relative to multiple containers.

0
votes

Ended up going with @Noah Stahl's suggestion. Leaving this here as an alternative.


Couldn't figure out how to do this directly, so came up with a work-around:

  1. Add function with CosmosDBTrigger on StockPrices collection with Queue output binding
  2. foreach over Documents from the trigger, serialize and add to the Queue
  3. Add function with QueueTrigger, CosmosDB input binding for Stocks collection (with PartitionKey and Id set to StockTicker), and CosmosDB output binding for Stocks collection
  4. Update Stock from CosmosDB input binding with values from the QueueTrigger
  5. Assign updated Stock to CosmosDB output binding parameter (updates record in DB)

This said, I'd like to hear about more straightforward ways of doing this, as my approach seems like a hack.