.NET で Firestore

Firebase を使ってアプリをサクッと作れるようになりたかったので勉強することにした。まずは Firestore。アプリは Xamarin で作るつもりなので、C# から Firestore を触ってみる。NuGet で専用のパッケージが公開されているので、それを使う。まだベータ版だけど、Firestore 自体まだベータ版だし。

www.nuget.org

Firestore で CRUD をやるサンプルを書いてみた。コードはサクッと書けたけど、GCP 外から Firestore にアクセスするために必要な、アクセスキーファイルを入手するのが最初にして最大の関門だった。GCP の 「API とサービス」の「認証情報」でサービスアカウントを作成して、アクセスキーファイルをダウンロードしておかないといけない。

using Google.Cloud.Firestore;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace FirestoreSample
{
    class Program
    {
        const string ProjectId = "your-project-id";

        static void Main(string[] args)
        {
            // API とサービスの認証情報でサービスアカウントを作成し、
            // ダウンロードしたアクセスキーファイルのパスを環境変数で指定
            Environment.SetEnvironmentVariable(
                "GOOGLE_APPLICATION_CREDENTIALS",
                Path.Combine(AppContext.BaseDirectory, "your-key.json"));

            MainAsync().GetAwaiter().GetResult();

            Console.WriteLine("Press Enter Key.");
            Console.ReadLine();
        }

        static async Task MainAsync()
        {
            var db = FirestoreDb.Create(ProjectId);

            // books コレクションにドキュメント追加
            var book1Ref = await db.Collection("books")
                .AddAsync(new Dictionary<string, object>()
                {
                    ["title"] = "かぐや様は告らせたい",
                    ["price"] = 500,
                });

            // books コレクションに ID 指定でドキュメント追加
            var book2Ref = db.Collection("books").Document("bokuben");
            await book2Ref.CreateAsync(new Dictionary<string, object>()
            {
                ["title"] = "ぼくたちは勉強ができない",
                ["price"] = 450,
            });

            // books を価格順にソートして取得
            var querySnapshot = await db.Collection("books")
                .OrderBy("price")
                .GetSnapshotAsync();
            foreach (var doc in querySnapshot.Documents)
            {
                Console.WriteLine($"{doc.GetValue<string>("title")}({doc.GetValue<int>("price")}円)");
            }

            // ドキュメントを更新
            await db.Collection("books")
                .Document("bokuben")
                .SetAsync(new Dictionary<string, object>()
                {
                    ["price"] = 420,
                }, SetOptions.MergeAll);

            // ID を指定して 1 件取得
            var documentSnapshot = await db.Collection("books")
                .Document("bokuben")
                .GetSnapshotAsync();
            Console.WriteLine($"{documentSnapshot.GetValue<string>("title")}({documentSnapshot.GetValue<int>("price")}円)");

            // ドキュメントを削除
            await db.Collection("books")
                .Document(book1Ref.Id)
                .DeleteAsync();
            await db.Collection("books")
                .Document("bokuben")
                .DeleteAsync();
        }
    }
}

実行してみた結果は下の通り。

f:id:griefworker:20180904163909p:plain

Xamarin だとロジックの大部分を iOSAndroid で共有できるので、Firestore を単純にデータベースとして使い、ロジックを .NET Stadard ライブラリとして書いて、iOSAndroid から使う戦略が使えそう。