Share via


Azure テーブルで Azure SDK for Go を使用する方法

適用対象: Table

ヒント

この記事の内容は、Azure Table Storage と Azure Cosmos DB for Table に適用されます。 API for Table は、スループット最適化テーブル、グローバル分散、自動セカンダリ インデックスを提供する Table Storage 用のプレミアムなオファーです。

この記事では、Azure SDK for Go を使用して Azure テーブル エンティティとテーブル エンティティを作成、一覧表示、削除する方法について説明します。

Azure テーブルを使用すると、スキーマなしの設計のキー属性ストアが提供されることにより、構造化された NoSQL データをクラウドに格納できます。 Azure テーブル ストレージはスキーマがないため、アプリケーションの進化するニーズに合わせてデータを容易に適応できます。 テーブルのデータと API へのアクセスは、多くのアプリケーションにとって高速でコスト効率の高いソリューションです。

テーブル ストレージまたは Azure Cosmos DB を使用すると、Web アプリケーションのユーザー データ、アドレス帳、デバイス情報など、柔軟なデータセットを格納できます。 または、サービスに必要なその他の種類のメタデータ。 ストレージ アカウントの容量の上限を超えない限り、テーブルには任意の数のエンティティを保存でき、ストレージ アカウントには任意の数のテーブルを含めることができます。

この記事に従って、Azure SDK for Go を使用して Azure テーブル ストレージを管理する方法について確認してください。

前提条件

環境を設定する

このチュートリアルに従うには、Azure リソース グループ、ストレージ アカウント、テーブル リソースが必要です。 次のコマンドを実行して、環境を設定します。

  1. Azure リソース グループを作成します。

    az group create --name myResourceGroup --location eastus
    
  2. 次に、新しい Azure テーブル用の Azure ストレージ アカウントを作成します。

    az storage account create --name <storageAccountName> --resource-group myResourceGroup --location eastus --sku Standard_LRS
    
  3. テーブル リソースを作成します。

    az storage table create --account-name <storageAccountName> --account-key 'storageKey' --name mytable
    

パッケージのインストール

Go で Azure テーブルを管理するには、azidentityaztables の 2 つのパッケージが必要です。 azidentity パッケージには、Azure に対する認証方法が用意されています。 aztables パッケージを使用すると、Azure でテーブル リソースを管理できます。 次の Go コマンドを実行して、これらのパッケージをインストールします。

go get github.com/Azure/azure-sdk-for-go/sdk/data/aztables
go get github.com/Azure/azure-sdk-for-go/sdk/azidentity

Azure に対する認証方法の詳細については、「Azure SDK for Go での Azure 認証」を参照してください。

サンプル アプリケーションを作成する

パッケージをインストールしたら、Azure SDK for Go を使用して Azure テーブルを管理するサンプル アプリケーションを作成します。 go mod コマンドを実行して、azTableSample という名前の新しいモジュールを作成します。

go mod init azTableSample

次に、main.go という名前のファイルを作成し、下の内容をそこにコピーします。

package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
    "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
    "github.com/Azure/azure-sdk-for-go/sdk/data/aztables"
)

type InventoryEntity struct {
    aztables.Entity
    Price       float32
    Inventory   int32
    ProductName string
    OnSale      bool
}

type PurchasedEntity struct {
    aztables.Entity
    Price float32
    ProductName string
    OnSale bool
}

func getClient() *aztables.Client {
    accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT")
    if !ok {
        panic("AZURE_STORAGE_ACCOUNT environment variable not found")
    }

    tableName, ok := os.LookupEnv("AZURE_TABLE_NAME")
    if !ok {
        panic("AZURE_TABLE_NAME environment variable not found")
    }

    cred, err := azidentity.NewDefaultAzureCredential(nil)
    if err != nil {
        panic(err)
    }
    serviceURL := fmt.Sprintf("https://%s.table.core.windows.net/%s", accountName, tableName)
    client, err := aztables.NewClient(serviceURL, cred, nil)
    if err != nil {
        panic(err)
    }
    return client
}

func createTable(client *aztables.Client) {
    //TODO: Check access policy, Storage Blob Data Contributor role needed
    _, err := client.Create(context.TODO(), nil)
    if err != nil {
        panic(err)
    }
}

func addEntity(client *aztables.Client) {
    myEntity := InventoryEntity{
        Entity: aztables.Entity{
            PartitionKey: "pk001",
            RowKey:       "rk001",
        },
        Price:       3.99,
        Inventory:   20,
        ProductName: "Markers",
        OnSale:      false,
    }

    marshalled, err := json.Marshal(myEntity)
    if err != nil {
        panic(err)
    }

    _, err = client.AddEntity(context.TODO(), marshalled, nil) // TODO: Check access policy, need Storage Table Data Contributor role
    if err != nil {
        panic(err)
    }
}

func listEntities(client *aztables.Client) {
    listPager := client.List(nil)
    pageCount := 0
    for listPager.More() {
        response, err := listPager.NextPage(context.TODO())
        if err != nil {
            panic(err)
        }
        fmt.Printf("There are %d entities in page #%d\n", len(response.Entities), pageCount)
        pageCount += 1
    }
}

func queryEntity(client *aztables.Client) {
    filter := fmt.Sprintf("PartitionKey eq '%v' or RowKey eq '%v'", "pk001", "rk001")
    options := &aztables.ListEntitiesOptions{
        Filter: &filter,
        Select: to.StringPtr("RowKey,Price,Inventory,ProductName,OnSale"),
        Top:    to.Int32Ptr(15),
    }

    pager := client.List(options)
    for pager.More() {
        resp, err := pager.NextPage(context.Background())
        if err != nil {
            panic(err)
        }
        for _, entity := range resp.Entities {
            var myEntity PurchasedEntity 
            err = json.Unmarshal(entity, &myEntity)
            if err != nil {
                panic(err)
            }
            fmt.Println("Return custom type [PurchasedEntity]")
            fmt.Printf("Price: %v; ProductName: %v; OnSale: %v\n", myEntity.Price, myEntity.ProductName, myEntity.OnSale)
        }
    }
}

func deleteEntity(client *aztables.Client) {
    _, err := client.DeleteEntity(context.TODO(), "pk001", "rk001", nil)
    if err != nil {
        panic(err)
    }
}

func deleteTable(client *aztables.Client) {
    _, err := client.Delete(context.TODO(), nil)
    if err != nil {
        panic(err)
    }
}

func main() {

    fmt.Println("Authenticating...")
    client := getClient()

    fmt.Println("Creating a table...")
    createTable(client)

    fmt.Println("Adding an entity to the table...")
    addEntity(client)

    fmt.Println("Calculating all entities in the table...")
    listEntities(client)

    fmt.Println("Querying a specific entity...")
    queryEntity(client) 

    fmt.Println("Deleting an entity...")
    deleteEntity(client) 

    fmt.Println("Deleting a table...")
    deleteTable(client)
}

重要

認証に使用するアカウントに、Azure ストレージ アカウントを管理するための適切なアクセス ポリシーがあることを確認してください。 上のコードを実行するには、アカウントに少なくともストレージ BLOB データ共同作成者ロールとストレージ テーブル データ共同作成者ロールが必要です。

コード例

クライアントを認証する

// Lookup environment variables
accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT")
if !ok {
  panic("AZURE_STORAGE_ACCOUNT environment variable not found")
}

tableName, ok := os.LookupEnv("AZURE_TABLE_NAME")
if !ok {
  panic("AZURE_TABLE_NAME environment variable not found")
}

// Create a credential
cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
  panic(err)
}

// Create a table client
serviceURL := fmt.Sprintf("https://%s.table.core.windows.net/%s", accountName, tableName)
client, err := aztables.NewClient(serviceURL, cred, nil)
if err != nil {
  panic(err)
}

テーブルを作成する

// Create a table and discard the response
_, err := client.Create(context.TODO(), nil)
if err != nil {
  panic(err)
}

エンティティの作成

// Define the table entity as a custom type
type InventoryEntity struct {
    aztables.Entity
    Price       float32
    Inventory   int32
    ProductName string
    OnSale      bool
}

// Define the entity values
myEntity := InventoryEntity{
    Entity: aztables.Entity{
        PartitionKey: "pk001",
        RowKey:       "rk001",
    },
    Price:       3.99,
    Inventory:   20,
    ProductName: "Markers",
    OnSale:      false,
}

// Marshal the entity to JSON
marshalled, err := json.Marshal(myEntity)
if err != nil {
    panic(err)
}

// Add the entity to the table
_, err = client.AddEntity(context.TODO(), marshalled, nil) // needs Storage Table Data Contributor role
if err != nil {
    panic(err)
}

エンティティを取得する

// Define the new custom type
type PurchasedEntity struct {
    aztables.Entity
    Price       float32
    ProductName string
    OnSale      bool
}

// Define the query filter and options
filter := fmt.Sprintf("PartitionKey eq '%v' or RowKey eq '%v'", "pk001", "rk001")
options := &aztables.ListEntitiesOptions{
    Filter: &filter,
    Select: to.StringPtr("RowKey,Price,Inventory,ProductName,OnSale"),
    Top:    to.Int32Ptr(15),
}

// Query the table for the entity
pager := client.List(options)
for pager.More() {
    resp, err := pager.NextPage(context.Background())
    if err != nil {
        panic(err)
    }
    for _, entity := range resp.Entities {
        var myEntity PurchasedEntity
        err = json.Unmarshal(entity, &myEntity)
        if err != nil {
            panic(err)
        }
        fmt.Println("Return custom type [PurchasedEntity]")
        fmt.Printf("Price: %v; ProductName: %v; OnSale: %v\n", myEntity.Price, myEntity.ProductName, myEntity.OnSale)
    }
}

エンティティを削除する

_, err := client.DeleteEntity(context.TODO(), "pk001", "rk001", nil)
if err != nil {
  panic(err)
}

テーブルを削除する

_, err := client.Delete(context.TODO(), nil)
if err != nil {
  panic(err)
}

コードの実行

後はアプリケーションを実行するだけです。 ただし、その前に環境変数を設定する必要があります。 次のコマンドを使用して、2 つの環境変数を作成し、適切な値に設定します。

export AZURE_STORAGE_ACCOUNT=<YourStorageAccountName> 
export AZURE_TABLE_NAME=<YourAzureTableName>

次に、次の go run コマンドを実行してアプリを実行します。

go run main.go

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

次のコマンドを実行して、リソース グループと残りすべてのリソースを削除します。

az group delete --resource-group myResourceGroup

次のステップ

このクイック スタートでは、Azure Cosmos DB アカウントを作成し、データ エクスプローラーを使用してテーブルを作成し、アプリを実行する方法を説明しました。 これで、Table 用 API を使用してデータに対してクエリを実行できるようになりました。