このエントリは2019/05/13現在の備忘録であり、以下のドキュメントの内容に対するメモです。将来この機能や設定方法が変わる可能性はあります。対象はFunction 2.xです。また、以下のコード例はいずれもJavaで記述しています。
Azure Functions 2.x 以降での Azure Cosmos DB のトリガーとバインドの概要 / Azure Cosmos DB trigger and bindings for Azure Functions 2.x and higher overview
https://docs.microsoft.com/azure/azure-functions/functions-bindings-cosmosdb-v2
Functionsをローカル環境でテストする場合(http://localhost:7071/…)、Azure Functions バインド拡張機能をインストールしておく必要がある。
Azure Functions バインド拡張機能を登録する / Register Azure Functions binding extensions
https://docs.microsoft.com/azure/azure-functions/functions-bindings-register
あと、Cosmos DBへの接続のための接続文字列は、ローカルテスト環境とAzure上では設定箇所が違うのでご注意を。
- ローカルテスト環境:local.settings.json
- 本番環境:Application settings > Connection strings
Trigger
Azure Cosmos DB のトリガーは Azure Cosmos DB 変更フィードを使用して、パーティション間の挿入と更新をリッスンします。 変更フィードは、削除ではなく挿入と更新を発行します。
Azure Functions 2.x 以降での Azure Cosmos DB のトリガー / Azure Cosmos DB trigger for Azure Functions 2.x and higher
https://docs.microsoft.com/azure/azure-functions/functions-bindings-cosmosdb-v2-trigger
変更されたドキュメントは変更順にリストとして出力される。@CosmosDBTriggerをアノテーションとして付加したFunctionが定期的に変更リストをポーリングしており、リストに追加があれば、そのFunctionsのロジックが動作する。
package cosmos2functions;
import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.annotation.CosmosDBTrigger;
import com.microsoft.azure.functions.annotation.FunctionName;
import java.util.List;
public class Function {
@FunctionName("cosmosDBMonitor")
public void cosmosDbLog(
@CosmosDBTrigger(
name = "CosmosDB2Functions",
databaseName = "database",
collectionName = "Items",
leaseCollectionName = "Leases",
createLeaseCollectionIfNotExists = true,
connectionStringSetting = "AzureCosmosDBConnection")
List<String> items,
final ExecutionContext context
) {
context.getLogger().info(items.size() + " item(s) is/are inserted.");
if (!items.isEmpty()) {
items.stream().forEach(s ->context.getLogger().info("Element: " + s));
}
}
}
取得できるのは変更された結果のドキュメントで、Stringとして取得してJSONObjectに変換すれば、変更データを取得できる。
なお、アノテーションで設定するプロパティは以下のドキュメントに記載がある。
CosmosDBTrigger Interface
https://docs.microsoft.com/java/api/com.microsoft.azure.functions.annotation.CosmosDBTrigger?view=azure-java-stable
ドキュメントに記載のないデフォルト値は以下の通り。
プロパティ | デフォルト値 |
name | |
dataType | “” |
databaseName | |
collectionName | |
leaseConnectionStringSetting | “” |
leaseCollectionName | “” |
leaseDatabaseName | “” |
createLeaseCollectionIfNotExists | false |
leasesCollectionThroughput | -1 |
leaseCollectionPrefix | “” |
checkpointInterval | -1 |
checkpointDocumentCount | -1 |
feedPollDelay | 5000 |
connectionStringSetting | |
leaseRenewInterval | 17000 |
leaseAcquireInterval | 13000 |
leaseExpirationInterval | 60000 |
maxItemsPerInvocation | -1 |
startFromBeginning | false |
preferredLocations | “” |
Input
SQL API を使用して 1 つ以上の Azure Cosmos DB ドキュメントを取得して関数の入力パラメーターに渡します。ドキュメント ID またはクエリ パラメーターは、関数を呼び出したトリガーに基づいて決定することができます。
Azure Functions 2.x 以降に対する Azure Cosmos DB の入力バインド / Azure Cosmos DB input binding for Azure Functions 2.x and higher
https://docs.microsoft.com/azure/azure-functions/functions-bindings-cosmosdb-v2-input
動的な条件設定のために、Query ParameterもしくはPath Parameterで渡す値を指定できる。ドキュメント上はPath Parameterをルートデータと表現している。Cosmos DBからPOJOもしくはStringとしてデータを取得できる。
Query Parameter (+ SQL Query)
Query Parameter(以下の例ではaddress)をFunctionに渡している。Function内では、指定されたAddressをwhere句に指定するSQL Queryを発行し、結果をPOJOとして取得、HTTP Responseとして返す。
このFunctionには、 <Function App URL>/api/cosmosDBInputMonitor でアクセスできる。
// Itemというクラスを作成しておく
@FunctionName("cosmosDBInputMonitor")
public HttpResponseMessage cosmosdbQuery(
@HttpTrigger(
name = "req",
methods = {HttpMethod.GET},
authLevel = AuthorizationLevel.ANONYMOUS)
HttpRequestMessage<Optional<String>> request,
@CosmosDBInput(
name = "CosmosDB2Functions",
databaseName = "database",
collectionName = "Items",
partitionKey = "{Query.address}",
sqlQuery = "select * from Items r where contains(r.address, {address})",
connectionStringSetting = "AzureCosmosDBConnection")
Item[] items,
final ExecutionContext context
) {
if (Optional.of(items).isPresent()) {
return request.createResponseBuilder(HttpStatus.OK)
.header("Content-Type", "application/json")
.body(items)
.build();
} else {
return request.createResponseBuilder(HttpStatus.NOT_FOUND)
.body("{\"error\":\"Not found\"}")
.build();
}
}
Path Parameter (+ SQL Query)
以下はPath Parameterで指定する例。この例では、
route = items/{address}
と設定しているため、このFunctionには、 <Function App URL>/api/items/{address} でアクセスできる。
// Itemというクラスを作成しておく
@FunctionName("cosmosDBInputMonitor2")
public HttpResponseMessage cosmosdbQuery2(
@HttpTrigger(
name = "req",
methods = {HttpMethod.GET},
authLevel = AuthorizationLevel.ANONYMOUS,
route = "items/{address}")
HttpRequestMessage<Optional<String>> request,
@CosmosDBInput(
name = "CosmosDB2Functions",
databaseName = "database",
collectionName = "Items",
sqlQuery = "select * from items r where contains(r.address, {address})",
connectionStringSetting = "AzureCosmosDBConnection")
Items[] items,
final ExecutionContext context
) {
if (Optional.of(items).isPresent()) {
return request.createResponseBuilder(HttpStatus.OK)
.header("Content-Type", "application/json")
.body(items)
.build();
} else {
return request.createResponseBuilder(HttpStatus.NOT_FOUND)
.body("{\"error\":\"Not found\"}")
.build();
}
}
アノテーションで設定するプロパティは以下のドキュメントに記載がある。
CosmosDBInput Interface
https://docs.microsoft.com/java/api/com.microsoft.azure.functions.annotation.cosmosdbinput?view=azure-java-stable
ドキュメントに記載のないデフォルト値は以下の通り。
プロパティ | デフォルト値 |
name | |
dataType | “” |
databaseName | |
collectionName | |
id | “” |
sqlQuery | “” |
connectionStringSetting | |
partitionKey | “” |
Output
Azure Cosmos DB 出力バインドを使用すると、SQL API を使って Azure Cosmos DB データベースに新しいドキュメントを記述できます。
Azure Functions 2.x 以降に対する Azure Cosmos DB の出力バインド / Azure Cosmos DB output binding for Azure Functions 2.x and higher
https://docs.microsoft.com/azure/azure-functions/functions-bindings-cosmosdb-v2-output
@CosmosDBOutput アノテーションをつける場合、以下の注意事項がある。
- Functionの戻り値をCosmos DBに格納することを意図している場合は、メソッドに注釈をつける
- Outputバインディングを使ってCosmos DBに格納することを意図している場合は、OutputBindingクラスインスタンスに注釈をつける
戻り値を格納する
POSTで複数の項目を入れて、Echo backするようなFunctionの例。このFunctionの戻り値をCosmos DBに格納している。
// 戻り値を格納したいので、 @CosmosDBOutputは外
@FunctionName("output1")
@CosmosDBOutput(name = "CosmosDB2Functions",
databaseName = "database",
collectionName = "Items",
connectionStringSetting = "AzureCosmosDBConnection")
public Item[] echo (
@HttpTrigger(
name = "req",
methods = {HttpMethod.POST},
authLevel = AuthorizationLevel.ANONYMOUS)
HttpRequestMessage<Optional<Item[]>> request,
final ExecutionContext context) {
return request.getBody().get();
}
戻り値としてrequest.getBody()ではなく、request.getBody().get()を指定しているのは、前者の場合、以下のようにvalue要素ごと格納されるため。
{
"value": {
....
}
}
OutputBindingを利用して格納する
この場合、メソッドの引数を使ってCosmos DBにデータを格納するため、@CosmosDBOutputは引数outputItemに対して指定していることに注意。
// OutputBindingを使うので、@CosmosDBOutputは引数outputItemに指定
@FunctionName("output2")
public HttpResponseMessage echo (
@HttpTrigger(
name = "req",
methods = {HttpMethod.POST},
authLevel = AuthorizationLevel.ANONYMOUS)
HttpRequestMessage<Optional<List<Item>>> request,
@CosmosDBOutput(
name = "CosmosDB2Functions",
databaseName = "database",
collectionName = "Items",
connectionStringSetting = "AzureCosmosDBConnection")
OutputBinding<List<Item>> outputItem,
final ExecutionContext context
) {
outputItem.setValue(request.getBody().get());
return request.createResponseBuilder(HttpStatus.CREATED)
.header("content-type","application/json")
.body(request.getBody().get())
.build();
}
アノテーションで設定するプロパティは以下のドキュメントに記載がある。
CosmosDBOutput Interface
https://docs.microsoft.com/java/api/com.microsoft.azure.functions.annotation.cosmosdboutput?view=azure-java-stable
ドキュメントに記載のないデフォルト値は以下の通り。
プロパティ | デフォルト値 |
name | |
dataType | “” |
databaseName | |
collectionName | |
createIfNotExists | false |
connectionStringSetting | |
partitionKey | “” |
collectionThroughput | -1 |
useMultipleWriteLocations | false |
preferredLocations | “” |