弊社ベーシックが開発・運用している ferret One と言うサービスではメインのデータベースに MongoDB を採用しています。昔は AWS の EC2 インスタンスで自前ホスティングをしていましたが、AWS RDS のようにマネージドサービスに移行をしたかったので、1年ほど前に MongoDB Atlas ( MongoDB 開発元が運営するクラウドサービス ) に移行しました。

MongoDB Atlas には Google の Firebase のように BaaS 機能を備えた Stitch というサービスがあります。この中に、MongoDB のデータ更新をトリガーに起動可能な Triggers や、アプリケーションから呼べる Functions サービスがあります。静的ページのホスティングも可能です。Firebase / Firestore + Cloud Functions のような関係ですね。

今回は MongoDB Stitch の Triggers / Functions を紹介します。簡単便利でサーバレス生活を始められます。

MongoDB Atlas と Stitch の関係

紹介の前に個人的にわかりにくかった Atlas と Stitch の関係について軽く説明します。Atlas は MongoDB をホストしてくれるフルマネージドサービスです。Stitch は MongoDB をデータストアにクラウド上にアプリケーションを構築できる BaaS です。

Atlas に MongoDB のクラスタを作ると、標準で Triggers_StitchApp と言う名前で Stitch アプリが作成されます。分かりにくいのは、この自動で作られた Stitch アプリはアプリ一覧ページではなぜか表示されず隠されています。

Atlas の中の Triggers ページにひっそりとリンクがあります。僕はこれに気がつくまで30分ほど探し回りました…。

Triggers / Functions について

Triggers の特徴

  • 大きく3種類のトリガーがある
    • データ : ドキュメントが「作成」「更新」「削除」「置換」された時に Function を起動できる
    • 認証 : ユーザが作成・削除・ログインした時に Function を起動できる
    • スケジュール : CRON のように定期的に Function を起動できる
  • 操作の順序保証(順序保証せずパフォーマンスを優先することもできる)
  • 細かい起動条件を設定可能( publish フィールドが true に更新された時など)
  • Amazon EventBridge と連携可能

Functions の特徴

  • ES6 をサポート
  • 外部 npm パッケージ利用可能( zip で 10MB 以内)
  • 実行時間は 90 秒以内
  • 利用可能メモリは 256MB 以内
  • ヘッドレスブラウザの実行などはできない
  • ブラウザ / iOS / Android SDK から直接 Function を呼び出せる
  • Webhook を作り、HTTP Endpoint から Function を呼び出せる
  • Twilio API / GitHub Event からの受信で Function を呼び出せる

そのほか

  • 環境変数や秘匿情報を管理可能
  • GraphQL インターフェイスを利用可能(ベータ)
  • GCM を利用したプッシュ通知可能
  • collection の read/write ルールをユーザ単位で細かく制御可能(Firestore rule と似ている)

これだけでも Firebase のようにサーバレスでアプリが構築できそうな雰囲気があります。

Trigger のサンプル

exports = async function(changeEvent) {
  // 更新されたドキュメントデータを全部取得
  const fullDocument = changeEvent.fullDocument;

  // 指定 MongoDB クラスタに接続
  const mongodb = context.services.get("example-cluster");
  
  // 他の collection のデータ操作可能
  const foos = mongodb.db("database-name").collection("foo");
  const foo = await foos.findOne({_id: fullDocument.foo_id});
  
  // 標準で HTTP リクエストサポート  
  context.http.post({
    url: 'https://example.com/',
    body: { text: 'bar' },
    encodeBodyAsJSON: true
  });
};

デプロイについて

Triggers / Functions のデプロイは、いくつかの方法をサポートしています。

  • コンソールから手動
  • GitHub 連携
  • CLI ツール
  • Admin API

基本は、GitHub の push をトリガーにしたデプロイと、CI に CLI を組み込んだデプロイを使うと思います。どちらも使い方は簡単で特に GitHub に関しては、リポジトリ連携をしたら即使える便利さです。

ソースコード管理について

Triggers / Functions の設定やソースコードは、コンソールから操作可能ですが、CLI に Export / Import 機能があるため、手元に持ってきて git 管理することが可能です。コンソールで直接コードをいじってバグを混入したり、属人化してしまい MongoDB おじさんを生み出すと言う悲劇を避けられます。

# CLI のインストールと設定
$ npm install -g mongodb-stitch-cli
$ stitch-cli login --api-key=hoge --private-api-key=piyo

# エクスポート
$ stitch-cli export --app-id=app-name --for-source-control

料金について

MongoDB 自体のホスティング料金以外で、Triggers / Functions にかかる料金は、Function が使ったメモリ使用量と実行時間と呼び出し回数によって決まります。2020/06/07 時点では、月に100万回の呼び出しまでは無料枠になるようです。超えた場合もそこまで高額じゃないです。詳しくは料金ページを参照してください。

まとめ

と言う感じで MongoDB をより便利に使える Stitch の Triggers / Functions の紹介でした。AWS にも MongoDB 互換性のある DocumentDB がありますが、MongoDB Stitch ほどの機能はないため、より活用したい人は検討すると良いと思います。

MongoDB Atlas の基盤自体は AWS / GCP / Azure をベースにしているので、AWS にアプリケーションサーバがあっても、VPC で東京リージョン MongoDB Atlas に接続ができたりします。ここ1年ほど大きなトラブルもなく安定稼働をしているのでオススメです。