Azure Cosmos DBについて② ~試しに触ってみる~

f:id:ecb_tkaihatsu:20201130092545p:plain

はじめに

ブンブンHello World.

どうも開発です。

前回Azure Cosmos DBについての記事を投稿いたしました。 本記事と合わせて、ぜひご一読ください。

Cosmos DBについて、というより NoSQL について の方が正しいかもしれませんが…(;'∀')

今回はそんなCosmosDBについての記事その2です。 本記事では、Node.jsの環境を利用して無料でサクッとCosmosDBに触れてみる といった内容になっております。

今回は、「Azureとは?」「Cosmos DBってどうやって使うの?」といったことに焦点を当てて解説したいと思います。

Azure と Cosmos DB

Cosmos DBを試してみる前に、まずはCosmos DBのサービスを提供しているAzureについて知る必要があります。

Azure

AzureはMicrosoftが提供するクラウドサービスです。

Cosmos DBやApp Service、Azure FunctionsやVirtual Machineなど、幅広いサービスを提供しています。

AWSとどっちがいいんだ なんて比較もよくされますね。

Azureで提供されているサービスは無料で利用できるものとそうでないものがあるので注意しましょう。

「クラウド破産」なんて俗語もありますので、気を付けていきたいですね。

Cosmos DB

Cosmos DBはAzureで提供されているNoSQLサービスです。

Cosmos DBではデータをキーバリューの状態やドキュメント、グラフとして構造化し格納/取得することができます。 これらの機能はCosmos DBのSQL API、Cassandra API、MongoDB API、Gremlin API等から選択することで実現することができます。

また、.NET、Java、Node.js、Python等メジャーな言語で提供されているSDKを利用することで、Cosmos DBを利用したアプリを構築することができます。

詳しい内容は前回記事を参照してください。

実際にやってみた

そんなこんなでAzureとCosmos DBについて理解出来たら、さっそく使ってみましょう!

構成

今回試しに触ってみるにあたって、アプリケーションの構成は下記のようにしたいと思います。

Azure側:Cosmos DB

フロントエンド:Node.js

今回は単純な動作検証のため、フロントエンドから直接Cosmos DBのAPIを呼び出して使ってみたいと思います。

準備

それではまずAzure側から構築していきましょう。

Cosmos DBは無料で利用することができるので、今回はそれを活用してノーコストで検証してみたいと思います。

Azureに登録

クレジットカードが必要なので用意しておきましょう。

2021/04/16現在、Azureでは12ヵ月の無料利用枠が用意されています。

もし初めてAzureを利用する方は、是非利用してみてください!

Cosmos DB以外にも様々なサービスを試すことができます。

リソースグループの作成

登録が完了したら、次はリソースグループの作成を行います。

リソースグループとは、App ServiceやCosmos DBなどの各リソースをまとめておくためのくくりです。

Azureポータルにアクセスしたら、下記画像のように「リソースグループ」を選択します。 f:id:ecb_tkaihatsu:20210324125526p:plain

選択すると現在のリソースグループ一覧が表示されますので、メニューの「+作成」を選択します。 f:id:ecb_tkaihatsu:20210324125540p:plain

下記がリソースグループ作成画面です。

サブスクリプションは作成したサブスクリプション名、リソースグループは任意の名称を付けましょう。 リージョンは東日本がおススメです。 西日本もありますが、東日本と使えるサービスに若干の差異がある場合があるのでご注意ください。 国外リージョン(米国東部など)も同様です。 f:id:ecb_tkaihatsu:20210324125549p:plain

リソースの作成

リソースグループが出来上がったら、いよいよCosmos DBを作成しましょう!

以下の画面に従って作成していきます。

まずはリソースグループの上部メニューから「+追加」を選択します。 f:id:ecb_tkaihatsu:20210324125915p:plain


一覧から「Azure Cosmos DB」を選択します。 f:id:ecb_tkaihatsu:20210324125925p:plain


Cosmos DBのアカウント名を設定し、API、場所、容量モードを選択します。 APIはコア(SQL)、場所は東日本、容量モードはプロビジョニングされたスループットを選びましょう。 geo冗長性などのオプションについては、すべて無効にしておきましょう。 f:id:ecb_tkaihatsu:20210324125936p:plain

APIについてはSQL以外にCassandraやMongoDBなど、豊富なAPIがありますので用途に合ったものを選択しましょう。

docs.microsoft.com

注意点として、Cosmos DBは1サブスクリプションに対して1Cosmos DBアカウントが無料プラン(Free Tier)を利用することができるため、複数のCosmos DBアカウントを作成する場合はご注意ください。 また、無料プランはプロビジョニングされたスループットに対して、最初の5GB、400RUまでを無料とし、超過した分は料金が発生するため使い過ぎに注意しましょう。 RUについては前回の記事で触れているので、そちらをご参照ください。

無料プランの対象になっていない場合は、画像の赤線のような注意書きが表示されます。

いざ実践

リソースの準備までできれば、Azure側で設定する内容はOKです。

ここからはNode.js環境で実際にCosmos DBを利用してみたいと思います。

Node.js環境の構築

それではローカルの実行環境を構築していきたいと思います。

ローカル環境を構築してから実際にCosmos DBに接続するまでに、下記の手順を行います。

  1. Node.jsをインストール
  2. プロジェクトを作成
  3. npmコマンドでCosmos DBのモジュールをインストール
  4. コードを編集
  5. 実行

手順1,2については様々な記事があるので、本記事では省略いたします。

手順3のCosmos DBのモジュールは、下記コマンドでインストールします。

npm install @azure/cosmos --save

手順4,5については、次の項で説明いたします。

ソース

それでは、実際にCosmos DBを利用するための設定を見ていきましょう。

ディレクトリ構造は下記のようにしたいと思います。

cosmos_test
 ┣ node_modules
 ┣ src
 ┃  ┣ azure_cosmos
 ┃  ┃  ┣ cosmos.js
 ┃  ┃  ┗ config.js
 ┃  ┗ index.js
 ┣ package.json
 ┗ package-lock.json

それでは、上記ディレクトリ構造に従ってサンプルソースを実装していきます。



まず初めに、Cosmos DBに接続するための情報を保管しておくconfig.jsを作成していきます。 config.jsの中身は下記のようになります。

config.js

// @ts-check

const config = {
    endpoint: "エンドポイントURL",
    key: "Cosmos DBの接続キー",
    databaseId: "データベースID",
    containerId: "コンテナID",
    partitionKey: { kind: "Hash", paths: ["論理パーティションに利用する要素"] }
};
module.exports = { config };

上記設定項目は、AzureポータルのCosmos DBページ左メニューから値を取得することができます。

エンドポイントURLには下記画像のURLを、Keyには接続キーを設定します。

接続キーについてはプライマリ、セカンダリどちらを設定しても構いません。

f:id:ecb_tkaihatsu:20210324192716p:plain

データベースIDについては生成したデータベース名を、コンテナIDは生成したコンテナIDを設定します。 pathsについては、設定した論理パーティションを設定します。

⚠注意⚠

注意点として、接続キーなどの情報をGithubのパブリックリポジトリなど、不特定多数アクセスが可能な場所にアップロードしてしまうと、セキュリティ情報を全世界に対して公開してしまうことになるので注意しましょう。 適宜環境変数に持たせておいて、上記ファイルでは環境変数を呼び出すといった処理や、そもそもアップロードしないといった対策が必要になります。



続いて、実際にCosmos DBに対してコネクションを確立したり、SELECTなどのクエリを発行する関数をまとめたcosmos.jsを作成していきます。

cosmos.jsは下記のようになります。

cosmos.js

//@ts-check
const { config } = require("./config");
const CosmosClient = require("@azure/cosmos").CosmosClient;

async function createCosmosDbClient() {
    const { endpoint, key, databaseId, containerId, partitionKey } = config;
    const client = new CosmosClient({ endpoint, key });
    await client.databases.createIfNotExists({
        id: databaseId,
    });
    const { container } = await client
        .database(databaseId)
        .containers.createIfNotExists({ id: containerId, partitionKey }, { offerThroughput: 400 });
    return container;
}

async function selectAll(container) {
    const querySpec = {
        query: "SELECT * from c",
    };
    const { resources: items } = await container.items
        .query(querySpec)
        .fetchAll();

    return items;
}

async function insertData(container, data) {
    return await container.items.create(data);
}

module.exports = { createCosmosDbClient, selectAll, insertData };

Cosmos DBからデータを取ってくる関数selectAll()について、本サンプルでは関数内でクエリを定義し、その実行結果をreturnで返しています。

selectAll()で定義しているquery: "SELECT * from c",ですが、このクエリで呼び出しているcはコレクション(collection)=コンテナの中身全体を指しています(collectionの略かどうかは不明。詳細を把握されている方はコメントで教えていただければ幸いです)。

Cosmos DBではSELECT句以外(FROMWHERE)は基本的にオプションとして定義されています。詳細は下記リンクを参照ください。

docs.microsoft.com

Cosmos DBのコンテナにレコードを追加するinsertData()は、第二引数で渡したオブジェクトがそのままレコードとしてCosmos DBに格納されます。



最後に実行の起点となるindex.jsを作成していきます。 index.jsは下記のようにします。

index.js

// @ts-check
const {
    createCosmosDbClient,
    selectAll,
    insertData,
} = require("./azure_cosmos/cosmos");

// Cosmos DBのコネクションを生成
const container = createCosmosDbClient();

container.then((container) => {
    // コンテナから全件取得
    const queryResult = selectAll(container).then((result) => {
        return result;
    });

    queryResult.then((result) => {
        console.log(result);
    });

    // コンテナにデータを追加
    const insertResult = insertData(container, {
        id: "",
        BookTitle: "ほげほげ",
        Author: "fuga-fuga",
        Publisher: "test",
        Cover: "https://xxxx.jpg",
        Text: "この本は…",
        reviews: [{
                Reviewer: "でぃべろ",
                Comment: "…",
            },
            {
                Reviewer: "開発",
                Comment: "……",
            },
        ],
    });

    insertResult.then((result) => {
        if (result.statusCode === 201) {
            console.log("success!");
        } else {
            console.log(result);
        }
    });
});

index.jsでは、初めにcreateCosmosDbClient()でコネクションを生成しています。

こちらが解決できたら、selectAll()で全件取得、insertData()でデータを追加という操作を行っています。

それでは、実際に実行して結果を確認してみましょう!

実行結果

正常に実行された場合、次のような結果になります。

コンテナへデータ追加が正常に終わった場合は「success!」の文字がコンソールに表示されます。 また、SELECTで取ってきたデータ一覧が表示されます。

f:id:ecb_tkaihatsu:20210324105512p:plain

ここで表示されている_rid_self_etag_attachments_tsについてはCosmos DBにレコードが登録された際に自動的に付与されるデータになります。 これらはユーザー側で任意の値を書き込むことはできないのでご注意ください。 スキーマを定義する際に_(アンダーバー)を項目名に利用しないのが賢明でしょう。 これらの値については下記を参照ください。

docs.microsoft.com

また、idについてはユーザー側で値を指定しない場合は、システム側で一意の値を自動で割り振ってくれます。


コンテナにデータが数件入っていた場合は、下記のように表示されます。

f:id:ecb_tkaihatsu:20210324105525p:plain

なお、今回のサンプルソースではSELECTもINSERTも非同期処理で実装されているため、必ず先にSELECTの結果が表示されるといったことは無く、先に処理が終わった順に表示されます。 この辺りは実装を少し調整することで解決できる問題ですね。

まとめ

今回はNode.js環境を利用してCosmos DBを実際に触ってみるところまで解説いたしました。 本格的に利用する場合は接続情報を環境変数に持って秘匿したりといった処理が必要ですが、まずはお試しで触ってみる分にはこのくらいでも十分だと思います。

今回の例として重要な点は、

  • NoSQLを
  • 無料で
  • 簡単に

試すことができるというところです。

本記事ではSELECTとINSERTについての例を示しましたが、UPDATEやDELETEももちろん可能となっています。 詳細なチュートリアルはMicrosoft公式の記事もありますので、併せてご確認ください。

docs.microsoft.com

おわりに

コード全体で100行未満でCosmos DBを試すことができました。

このように非常にお手軽に試すことができるので、ぜひ一度触ってみてください!

高速さと柔軟性に無限の可能性を感じることができます!


~ecbeingでは無限の可能性を持ったエンジニアを大募集中です!~

careers.ecbeing.tech