クイック スタート: Azure Functions を使用して Azure Cosmos DB のデータベースの変更に対応する

このクイック スタートでは、Visual Studio Code を使用して、Azure Cosmos DB の No SQL データベースのデータベース変更に応答するアプリを構築します。 コードをローカルでテストした後、Azure Functions の Flex 従量課金プランで実行して作成した新しいサーバーレス関数アプリにデプロイします。

プロジェクト ソースでは、Azure Developer CLI (azd) 拡張機能とVisual Studio Codeを使用して、プロジェクト コードのローカルでの初期化と検証を簡略化し、コードをAzureにデプロイします。 このデプロイは、セキュリティで保護されたスケーラブルな Azure Functions デプロイの最新のベスト プラクティスに従います。

Flex Consumption プランは pay-for-what-you-use 課金モデルに従いますが、このコード プロジェクトでは、Azure Cosmos DB インスタンスを含む追加のAzure リソースが作成されます。 継続的な料金が発生しないように、完了したら 必ずリソースをクリーンアップ してください。

この記事では、Azure Functionsの Node.js プログラミング モデルのバージョン 4 をサポートします。

この記事では、Azure FunctionsのPython プログラミング モデルのバージョン 2 をサポートします。

[前提条件]

  • Node.js 18.x 以降。 node --version コマンドを使用して、現在のバージョンを確認してください。

プロジェクトを初期化する

Azure Developer CLI (azd) を使用して、テンプレートからローカル Azure Functions コード プロジェクトを作成します。

  1. ターミナルから次の azd init コマンドを実行して、テンプレートからローカル プロジェクトを作成します。

    azd init --template functions-quickstart-dotnet-azd-cosmosdb -e cosmosdbchanges-dotnet
    

    このコマンドは、template リポジトリからプロジェクト ファイルをプルし、新しいフォルダー内のプロジェクトを初期化します。 azd では、環境はアプリの一意のデプロイ コンテキストを維持するために使用され、複数を定義できます。 また、Azure で作成するリソース グループの名前の一部でもあります。

  2. プロジェクト ディレクトリに移動します。

    cd functions-quickstart-dotnet-azd-cosmosdb
    
  1. ターミナルから次の azd init コマンドを実行して、テンプレートからローカル プロジェクトを作成します。

    azd init --template functions-quickstart-java-azd-cosmosdb -e cosmosdbchanges-java
    

    このコマンドは、template リポジトリからプロジェクト ファイルをプルし、新しいフォルダー内のプロジェクトを初期化します。 azd では、環境はアプリの一意のデプロイ コンテキストを維持するために使用され、複数を定義できます。 また、Azure で作成するリソース グループの名前の一部でもあります。

  2. プロジェクト ディレクトリに移動します。

    cd functions-quickstart-java-azd-cosmosdb
    
  1. ターミナルから次の azd init コマンドを実行して、テンプレートからローカル プロジェクトを作成します。

    azd init --template functions-quickstart-javascript-azd-cosmosdb -e cosmosdbchanges-js
    

    このコマンドは、template リポジトリからプロジェクト ファイルをプルし、新しいフォルダー内のプロジェクトを初期化します。 azd では、環境はアプリの一意のデプロイ コンテキストを維持するために使用され、複数を定義できます。 また、Azure で作成するリソース グループの名前の一部でもあります。

  2. プロジェクト ディレクトリに移動します。

    cd functions-quickstart-javascript-azd-cosmosdb
    
  1. ターミナルから次の azd init コマンドを実行して、テンプレートからローカル プロジェクトを作成します。

    azd init --template functions-quickstart-powershell-azd-cosmosdb -e cosmosdbchanges-ps
    

    このコマンドは、template リポジトリからプロジェクト ファイルをプルし、新しいフォルダー内のプロジェクトを初期化します。 azd では、環境はアプリの一意のデプロイ コンテキストを維持するために使用され、複数を定義できます。 また、Azure で作成するリソース グループの名前の一部でもあります。

  2. プロジェクト ディレクトリに移動します。

    cd functions-quickstart-powershell-azd-cosmosdb
    
  1. ターミナルから次の azd init コマンドを実行して、テンプレートからローカル プロジェクトを作成します。

    azd init --template functions-quickstart-typescript-azd-cosmosdb -e cosmosdbchanges-ts
    

    このコマンドは、template リポジトリからプロジェクト ファイルをプルし、新しいフォルダー内のプロジェクトを初期化します。 azd では、環境はアプリの一意のデプロイ コンテキストを維持するために使用され、複数を定義できます。 また、Azure で作成するリソース グループの名前の一部でもあります。

  2. プロジェクト ディレクトリに移動します。

    cd functions-quickstart-typescript-azd-cosmosdb
    
  1. ターミナルから次の azd init コマンドを実行して、テンプレートからローカル プロジェクトを作成します。

    azd init --template functions-quickstart-python-azd-cosmosdb -e cosmosdbchanges-py
    

    このコマンドは、template リポジトリからプロジェクト ファイルをプルし、新しいフォルダー内のプロジェクトを初期化します。 azd では、環境はアプリの一意のデプロイ コンテキストを維持するために使用され、複数を定義できます。 また、Azure で作成するリソース グループの名前の一部でもあります。

  2. プロジェクト ディレクトリに移動します。

    cd functions-quickstart-python-azd-cosmosdb
    
  1. ローカル オペレーティング システムに応じて、次のコマンドを実行して、構成スクリプトに必要なアクセス許可を付与します。

    十分な特権で次のコマンドを実行します。

    chmod +x ./infra/scripts/*.sh
    
  2. Visual Studio Code でプロジェクトを開きます。

    code .
    

アプリをローカルで実行する前に、Azure でリソースを作成する必要があります。 このプロジェクトでは、Azure Cosmos DB のローカル エミュレーションは使用されません。

Azure リソースを作成する

このプロジェクトは、 azd provision コマンドを使用して、Flex Consumption プランで関数アプリを作成し、現在のベスト プラクティスに従った他の必要な Azure リソースと共に作成するように構成されています。

  1. Visual Studio Code で F1 キーを押してコマンド パレットを開き、コマンド Azure Developer CLI (azd): Sign In with Azure Developer CLIを検索して実行し、Azure アカウントを使用してサインインします。

  2. F1 キーを押してコマンド パレットを開き、コマンド Azure Developer CLI (azd): Provision Azure resources (provision)を検索して実行し、必要な Azure リソースを作成します。

  3. ターミナル ウィンドウでメッセージが表示されたら、次の必須のデプロイ パラメーターを指定します。

    Prompt Description
    使用する Azure サブスクリプションを選択する リソースを作成するサブスクリプションを選択します。
    location deployment パラメーター 新しい Azure リソースを含むリソース グループを作成する Azure リージョン。 現在、Flex 従量課金プランをサポートしているリージョンのみが表示されます。
    vnetEnabled デプロイ パラメーター テンプレートは仮想ネットワーク内でのリソースの作成をサポートしていますが、デプロイとテストを簡略化するために、 Falseを選択します。

    azd provision コマンドは、最新のベスト プラクティスに従って、これらのプロンプトに対する応答と Bicep 構成ファイルを使用して、これらの必要な Azure リソースを作成および構成します。

    • Flex 従量課金プランと関数アプリ
    • Azure Cosmos DB アカウント
    • Azure Storage (必須) と Application Insights (推奨)
    • ご自分のアカウントのアクセス ポリシーとロール
    • マネージド ID を使用したサービス間接続 (格納されている接続文字列の代わり)

    プロビジョニング後のフックでは、ローカルで実行するときに必要な local.settings.json ファイルも生成されます。 このファイルには、Azure の Azure Cosmos DB データベースに接続するために必要な設定も含まれています。

    ヒント

    プロビジョニング中に手順が失敗した場合は、問題を解決した後、 azd provision コマンドをもう一度再実行できます。

    コマンドが正常に完了したら、プロジェクト コードをローカルで実行し、Azure の Azure Cosmos DB データベースでトリガーできます。

関数をローカルで実行する

Visual Studio Code は Azure Functions Core ツール と統合され、Azure で新しい関数アプリに発行する前に、ローカル開発コンピューターでこのプロジェクトを実行できます。

  1. F1 キーを押し、コマンド パレットでコマンド Azurite: Startを検索して実行します。

  2. 関数をローカルで開始するには、F5 キーまたは、左側のアクティビティ バーの [実行とデバッグ] アイコンを押します。 ターミナル パネルに、Core Tools からの出力が表示されます。 アプリは ターミナル パネルで起動し、ローカルで実行されている関数の名前を確認できます。

    Windows での実行に問題がある場合、Visual Studio Code の既定のターミナルが WSL Bash に設定されていないことをご確認ください。

  3. Core Tools が ターミナルで実行されている状態で、 F1 キーを押し、コマンド パレットでコマンド NoSQL: Create Item... を検索して実行し、 document-db データベースと documents コンテナーの両方を選択します。

  4. 新しい Item.json ファイルの内容を次の JSON データに置き換え、[保存] を選択します。

    {
        "id": "doc1",
        "title": "Sample document",
        "content": "This is a sample document for testing my Azure Cosmos DB trigger in Azure Functions."
    }
    

    [保存] を選択すると、ターミナルで関数の実行が表示され、ローカル ドキュメントが更新され、サービスによって追加されたメタデータが含まれます。

  5. 完了したら、ターミナル ウィンドウで Ctrl + C キーを押して、func.exe ホスト プロセスを停止します。

コードの確認 (省略可能)

この関数は、Azure Cosmos DB NoSQL データベースの変更フィードに基づいてトリガーされます。

これらの環境変数は、トリガーが変更フィードを監視する方法を構成します。

  • COSMOS_CONNECTION__accountEndpoint: Cosmos DB アカウント エンドポイント
  • COSMOS_DATABASE_NAME: 監視するデータベースの名前
  • COSMOS_CONTAINER_NAME: 監視するコンテナーの名前

これらの環境変数は、 azd provision 操作中に Azure (関数アプリの設定) とローカル (local.settings.json) の両方で自動的に作成されます。

COSMOS_CONNECTION環境変数は、トリガーによって使用される Cosmos DB アカウント エンドポイントを構成します。 この環境変数は、azd provision 操作中に、Azure (関数アプリ設定) とローカル (local.settings.json) の両方で作成されます。 データベース名とコンテナー名は、トリガー構成で定義されます。

Azure Cosmos DB トリガーを定義するコードを確認できます。

using System;
using System.Collections.Generic;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;

namespace Company.Function
{
    public class CosmosTrigger
    {
        private readonly ILogger _logger;

        public CosmosTrigger(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<CosmosTrigger>();
        }

        [Function("cosmos_trigger")]
        public void Run([CosmosDBTrigger(
            databaseName: "%COSMOS_DATABASE_NAME%",
            containerName: "%COSMOS_CONTAINER_NAME%",
            Connection = "COSMOS_CONNECTION",
            LeaseContainerName = "leases",
            CreateLeaseContainerIfNotExists = true)] IReadOnlyList<MyDocument> input)
        {
            if (input != null && input.Count > 0)
            {
                _logger.LogInformation("Documents modified: " + input.Count);
                _logger.LogInformation("First document Id: " + input[0].id);
            }
        }
    }
    public class MyDocument
    {
        /// <summary>
        /// The unique identifier for the document.
        /// </summary>
        public required string id { get; set; }

        /// <summary>
        /// A text field in the document.
        /// </summary>
        public required string Text { get; set; }

        /// <summary>
        /// A numeric field in the document.
        /// </summary>
        public int Number { get; set; }

        /// <summary>
        /// A boolean field in the document.
        /// </summary>
        public bool Boolean { get; set; }
    }
}

完全なテンプレート プロジェクト hereを確認できます。

package com.function;

import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.annotation.CosmosDBTrigger;
import com.microsoft.azure.functions.annotation.FunctionName;

public class CosmosTrigger {

    @FunctionName("cosmos_trigger")
    public void run(
        @CosmosDBTrigger(
            name = "input",
            databaseName = "%COSMOS_DATABASE_NAME%",
            containerName = "%COSMOS_CONTAINER_NAME%",
            connection = "COSMOS_CONNECTION",
            leaseContainerName = "leases",
            createLeaseContainerIfNotExists = true
        ) Object[] items,
        final ExecutionContext context
    ) {
        if (items != null && items.length > 0) {
            context.getLogger().info("Documents modified: " + items.length);
            context.getLogger().info("First document Id: " + items[0].toString());
        }
    }
}

完全なテンプレート プロジェクト hereを確認できます。

const { app } = require('@azure/functions');

app.cosmosDB('cosmos_trigger', {
    connection: 'COSMOS_CONNECTION',
    databaseName: '%COSMOS_DATABASE_NAME%',
    containerName: '%COSMOS_CONTAINER_NAME%',
    leaseContainerName: 'leases',
    createLeaseContainerIfNotExists: true,
    handler: (documents, context) => {
        if (documents && documents.length > 0) {
            context.log(`Documents modified: ${documents.length}`);
            context.log(`First document Id: ${documents[0].id}`);
        }
    }
});

完全なテンプレート プロジェクト hereを確認できます。

import { app, InvocationContext } from "@azure/functions";

export async function cosmos_trigger(documents: unknown[], context: InvocationContext): Promise<void> {
    context.log(`Cosmos DB function processed ${documents.length} documents`);

    if (documents && documents.length > 0) {
        for (const doc of documents) {
            context.log(`First document: ${JSON.stringify(doc)}`);
            if (doc && typeof doc === "object" && "id" in doc) {
                context.log(`First document id: ${(doc as { id?: string }).id}`);
            }
        }
    } else {
        context.log("No documents found.");
    }
}


app.cosmosDB('cosmos_trigger', {
    connection: 'COSMOS_CONNECTION',
    databaseName: 'documents-db',
    containerName: 'documents',
    createLeaseContainerIfNotExists: true,
    handler: cosmos_trigger
});

完全なテンプレート プロジェクト hereを確認できます。

トリガーは、次の function.json ファイルで定義されます。

{
  "bindings": [
    {
      "type": "cosmosDBTrigger",
      "name": "InputDocuments",
      "direction": "in",
      "databaseName": "%COSMOS_DATABASE_NAME%",
      "containerName": "%COSMOS_CONTAINER_NAME%",
      "connection": "COSMOS_CONNECTION",
      "leaseContainerName": "leases",
      "createLeaseContainerIfNotExists": true
    }
  ]
}

次のコードは、トリガーの実行時に実行されます。

param($InputDocuments, $TriggerMetadata)

if ($InputDocuments -and $InputDocuments.Count -gt 0) {
    Write-Host "Documents modified: $($InputDocuments.Count)"
    Write-Host "First document Id: $($InputDocuments[0].id)"
}

完全なテンプレート プロジェクト hereを確認できます。

import os
import azure.functions as func
import logging

app = func.FunctionApp()


@app.cosmos_db_trigger(
    arg_name="documents",
    container_name=os.environ.get("COSMOS_CONTAINER_NAME"),
    database_name=os.environ.get("COSMOS_DATABASE_NAME"),
    connection="COSMOS_CONNECTION",
    create_lease_container_if_not_exists="true",
)
def cosmos_trigger(documents: func.DocumentList):
    logging.info("Python CosmosDB triggered.")
    logging.info(f"Documents modified: {len(documents)}")
    if documents:
        for doc in documents:
            logging.info(f"First document: {doc.to_json()}")
            logging.info(f"First document id: {doc.get('id')}")
    else:
        logging.info("No documents found.")

完全なテンプレート プロジェクト hereを確認できます。

関数コードをローカルで確認して確認したら、次にプロジェクトを Azure に発行します。

Azure にデプロイ

Visual Studio Code から azd deploy コマンドを実行して、Azure で既にプロビジョニングされているリソースにプロジェクト コードをデプロイできます。

  1. F1を押してコマンドパレットを開きます。

  2. コマンド Azure Developer CLI (azd): Deploy to Azure (deploy) を検索して実行します。

    azd deploy コマンドは、コードをパッケージし、デプロイ コンテナーにデプロイします。 その後、アプリが起動し、デプロイされたパッケージで実行されます。

    コマンドが正常に完了すると、アプリは Azure で実行されます。

Azure 上の関数を呼び出す

  1. Visual Studio Code で F1 キーを押し、コマンド パレットでコマンド Azure: Open in portalを検索して実行し、 Function appを選択して、新しいアプリを選択します。 必要に応じて、Azure アカウントでサインインします。

    このコマンドを実行すると、Azure portal で新しい関数アプリが開きます。

  2. メイン ページの [ 概要 ] タブで、関数アプリ名を選択し、[ ログ ] タブを選択します。

  3. Visual Studio Code の NoSQL: Create Item コマンドを使用して、前と同様にドキュメントをコンテナーに再度追加します。

  4. 監視対象コンテナー内の更新によって関数がトリガーされることを再度確認します。

コードを再デプロイする

azd deploy コマンドは、コード更新プログラムを関数アプリにデプロイする必要がある回数実行できます。

デプロイされたコード ファイルは常に最新のデプロイ パッケージによって上書きされます。

azd プロンプトに対する最初の応答と、azd によって生成された環境変数は、名前付き環境にローカルに格納されます。 azd env get-values コマンドを使用して、Azure リソースの作成時に使用された環境内のすべての変数を確認します。

リソースをクリーンアップする

関数アプリと関連リソースの操作が完了したら、次のコマンドを使用して関数アプリとその関連リソースを Azure から削除し、それ以上のコストが発生しないようにすることができます。

azd down --no-prompt

--no-prompt オプションは、確認なしでリソース グループを削除するように azd に指示します。

このコマンドは、ローカル コード プロジェクトには影響しません。