MongoDB Atlasで無料かつ手軽にDB環境を利用してみる


調べ物をしてて発見したMongoDB Atlasを触ってみます。
**自前でインストール不要、無料ですごく楽に始めることが出来るMongoDB公式のサービス**といったところでしょうか。

少し触ってみましたが、プロトタイピングやデモ作成に向いてそうな印象を受けたのでそういった目線で紹介してみます。

## MongoDBのDBaaS

> ![スクリーンショット 2020-12-30 22.39.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/cb1b4aa1-2431-e334-28cf-5a23d31527b0.png "スクリーンショット 2020-12-30 22.39.58.png")

https://www.mongodb.com/cloud/atlas


> Atlasを使うと、簡単にMongoDBのクラスタを作って、各種管理を行えます。
性能や機能は限定されるものの、無料で使える種類のクラスタもあります。

と紹介してくれている記事もあります。

> 参考: [MongoDB Atlasを使い始める (MongoDB as a Service)](https://qiita.com/nacam403/items/08c18a8234c82e2b304e)

全然ウォッチできてなかったけど便利なものが出てたんですね。

インフラ各社のサービスだと、AWSのDocumentDBやAzureのCosmosDBみたいな雰囲気を感じます。
似た雰囲気はありますが、各社の **各サービスより使い始めは楽な気がします**。

インフラの色々な管理の機能などがあるのが本来の推しポイントだとは思いますが、

個人的には、自前でインストールしてホスティングなどをしなくて良い、MongoDBをすごく楽に始めることが出来るといったところが良いなと思いました。

### クレカ登録など無しで無料で始められる

無料で使い始められるのは試しやすくて良いですね。完全無料でクレジットカード登録など無しで始められます。

> ![スクリーンショット 2020-12-30 23.41.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/c0d7119f-8ddf-9ba6-005f-042dd6f6c358.png "スクリーンショット 2020-12-30 23.41.02.png")

Freeプランでも基本機能に制限はなさそうです。

> [MongoDB AtlasがAWS/Azure/GCPにまたがるマルチクラウドクラスタ構成をマネージドサービスでサポート。特定のクラウドが全部落ちても影響しない運用が可能に](https://www.publickey1.jp/blog/20/mongodb_atlasawsazuregcp.html)

上位プランだとこういった、どこかのクラウドが落ちても大丈夫！みたいな機能が使えるみたいですね。

### 管理画面でデータ確認が楽

Web上で管理画面も付いていて、データやトラフィックの確認ができるのも良いですね。

データのインサートしてみた時の管理画面ですが **Firebaseっぽい**ですね。

> ![スクリーンショット 2020-12-30 23.46.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/d0807896-c1cf-ff72-af87-06db64ae2b62.png "スクリーンショット 2020-12-30 23.46.24.png")

> Cloud Firestoreの管理画面ぽい

### 移行も楽そう（な気がする）

最初の登録以降は通常のMongoDBと(アプリケーションのソースコードレベルだと)同様の使い勝手になるのも嬉しいです。

プロトタイプ的にサービスを作ってアクセスが増えそうだったら別のインフラにMongoDBを自前で設置して使えば接続情報を書き換えるだけで良さそうですよね。

例えばFirebaseで最初作ってたけど途中からMongoDBに変えよーみたいな場合（あるか分からないですが）と比べると楽だと思います。

データ移行に関しては機能があるのかは調べられて無いです。

## Mongo DB Atlasを使ってみる

まずは登録から

トップページのStart Freeボタンから始められます。

> https://www.mongodb.com/cloud/atlas/register 

>![スクリーンショット 2020-12-30 23.50.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/3f66ccff-90a4-7c89-cfe4-47962e03125e.png "スクリーンショット 2020-12-30 23.50.34.png")

プライバシーポリシー同意をして進みます。

> ![スクリーンショット 2020-12-30 23.53.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/f0f092cf-40ed-9b0d-f0f8-fc130a274e1f.png "スクリーンショット 2020-12-30 23.53.05.png")

オーガナイゼーション名やプロジェクト名を決めて、好きな言語を選択します。僕はJSにしました。

> ![スクリーンショット 2020-12-30 23.54.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/6fa1eb1e-b41c-93eb-1e31-8bdc75ece4da.png "スクリーンショット 2020-12-30 23.54.19.png")

つぎにプランですね、無料で使う場合は`Shared Clusters`です。

> ![スクリーンショット 2020-12-30 23.55.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/75fcf0f4-4ae3-0d7e-44bf-da3befbf6885.png "スクリーンショット 2020-12-30 23.55.35.png")
 
### AWS/GCP/Azureから裏側のインフラを選択できる

裏側でどこのインフラサービスを使うか選べる模様です。面白い。

> ![スクリーンショット 2020-12-30 22.35.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/4d28c7f9-af17-9e9f-3cad-e5ff8c65c338.png "スクリーンショット 2020-12-30 22.35.09.png")

比較的Azureを使うことが多いという理由だけでAzureを選んでみます。香港リージョンって選べるんですね。

実際にここで選ぶAWS,GCP,Azureが表側には出てこないので、 **フリー版で使う分には実際はなんでも良いと思います。**

> ![スクリーンショット 2020-12-30 22.37.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/501c7888-d98d-8fcf-8cd0-583f90011242.png "スクリーンショット 2020-12-30 22.37.21.png")

* Shared RAM
* 512 MBストレージ
* MongoDB 4.2
* バックアップなし

このときCluster Name（アプリ名的な）を変更できますが、僕はデフォルトのClustre0という名前で作成しました。

#### 補足: AWSとGCPとAzureの利用可能なアジアリージョンを見てみる

日本から使う場合はアジアリージョンを選択する場合が多いと思うので利用可能なアジアリージョンを覗いてみました。

* AWSはムンバイとシンガポール

> ![スクリーンショット 2020-12-30 23.57.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/5faa9fe5-490a-3d5d-c144-674f585b573c.png "スクリーンショット 2020-12-30 23.57.26.png")

* GCPは日本リージョンが使える

> ![スクリーンショット 2020-12-30 23.57.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/68eb8d36-c127-bad4-ef00-863296808070.png "スクリーンショット 2020-12-30 23.57.50.png")

* Azureは香港

> ![スクリーンショット 2020-12-30 23.58.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/410dc2f1-36b9-3ba5-314d-29cc82929253.png "スクリーンショット 2020-12-30 23.58.01.png")

僕はAzureにしてしまいましたが、日本で使う場合、GCP選択して日本リージョンが良いかもですね

### 接続情報を確認

次の画面で少し待ちます。 クラスター作成に時間がかかりました。`CONNECT`ボタンから接続情報を作成していきましょう。

> ![](https://i.gyazo.com/bf6437b2e0639cc223b6fb358af55978.png)

#### 1. 接続セキュリティ情報を作成

`Add a connection IP Adress`でIPアドレスの制限設定します。

> ![](https://i.gyazo.com/3a86d48f38d208b37c01c35b9d3d14f7.png)

とりあえずは制限なしの`Allow Access from Anywhere`にします。

> ![スクリーンショット 2020-12-30 22.49.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/3c250334-9bb4-c325-ec88-aebd4c0cd059.png "スクリーンショット 2020-12-30 22.49.18.png")

次にデータベースユーザー名とパスワードを作成します。

> ![スクリーンショット 2020-12-30 22.49.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/9887d1a4-61a7-25f0-4a37-fa48a9eee52a.png "スクリーンショット 2020-12-30 22.49.55.png")

設定していくと左下のプログレスバーが進んでいくので分かりやすいですね。

> ![スクリーンショット 2020-12-30 22.51.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/99a67d85-27b6-26df-fa13-43b5a9e915e9.png "スクリーンショット 2020-12-30 22.51.28.png")

#### 2. 接続方法の確認

次に接続方法を何にするか選択します。 これは接続サンプルを示してくれるだけなので、実際はどれを選んでも大丈夫です。

> ![スクリーンショット 2020-12-30 22.52.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/dc468e4a-408b-a70b-a9c4-3aea87cf8806.png "スクリーンショット 2020-12-30 22.52.46.png")

* shellから
* 各アプリケーションから
* GUIから

といった接続方法が選べます。今回はNode.jsで接続してみるので`Connect you application`を選択します。

> ![](https://i.gyazo.com/d9741ac8490c4bdc655f199ad2bcd73f.png)

サンプルも表示されて良いですね。僕の場合はこんな感じのサンプルが表示されました。

```js
const MongoClient = require('mongodb').MongoClient;
const uri = "mongodb+srv://ユーザー名:<password>@クラスター名.xxxx.mongodb.net/<dbname>?retryWrites=true&w=majority";
const client = new MongoClient(uri, { useNewUrlParser: true });
client.connect(err => {
  const collection = client.db("test").collection("devices");
  // perform actions on the collection object
  client.close();
});
```

`クラスター名.xxxx.mongodb.net`がこの時の僕のホスティング先のURL(xxxxは伏せ字)です、別で作成してみたら
`クラスター名.x30i0.mongodb.net`になどになっていたので、プランをどうするか、ホスティング先をどこのインフラにするかまたは作成するたびに変わっていそうです。

ちなみに<dbname>はオーガナイゼーション名になる模様です。

## Node.jsからアクセスしてみる

Node.jsはv15.5.0です。

```bash
$ npm init -y
$ npm i mongodb
```

と、まずは準備します。

### DeprecationWarning対応

app.jsなどを作成し、先程のサンプルをそのまま実行すると

```bash
$ node app.js
(node:24495) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
(Use `node --trace-deprecation ...` to show where the warning was created)
```

といった警告が出ます。

`useUnifiedTopology: true`を追加しろとのことですね。

> 参考: [mongooseでDeprecationWarning出たときの対応](https://tocie.net/?p=856)

ここを踏まえて接続サンプルを変更してみました。

```js
const MongoClient = require('mongodb').MongoClient;

const DB_NAME = `xxxxxx`;
const USER_NAME = `xxxxxx`;
const USER_PASSWD = `xxxxxxx`;
const HOST_NAME = `cluster0.xxxx.mongodb.net`; //クラスター名やホスティング先によって変わる

const uri = `mongodb+srv://${USER_NAME}:${USER_PASSWD}@${HOST_NAME}/${DB_NAME}?retryWrites=true&w=majority`;
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true});
client.connect(err => {
  const collection = client.db("test").collection("devices");
  // perform actions on the collection object
  console.log("Connected successfully to server");
  client.close();
});
```

実行すると無事に接続できました。

```bash
$ node app.js
Connected successfully to server
```

### データの追加

データの追加をしてみます。先程のコードのclient.connectの内部を書き換えてます。

testデータベースの、deviceコレクションにデータを追加します。

```js

//省略

client.connect(err => {

  const collection = client.db('test').collection('devices');
  // perform actions on the collection object
  console.log('Connected successfully to server');
  
  const documents = [
    { a: 1 },
    { a: 2 },
    { a: 3 }
  ];

  collection.insertMany(documents, (err, result) => {
    console.log('Inserted 3 documents into the collection');
    console.log(result);
    client.close();
  })
  
});

```

> 参考: [Node.jsからMongoDBに接続してみる](https://qiita.com/one-kelvin/items/c0c036f774f0b3b98ae5)

実行

```bash
$ node app.js
Connected successfully to server
Inserted 3 documents into the collection
{
  result: { ok: 1, n: 3, opTime: { ts: [Timestamp], t: 2 } },
  ops: [
    { a: 1, _id: 5fec8c55d967cf6260da05e1 },
    { a: 2, _id: 5fec8c55d967cf6260da05e2 },
    { a: 3, _id: 5fec8c55d967cf6260da05e3 }
  ],
  insertedCount: 3,
  insertedIds: {
    '0': 5fec8c55d967cf6260da05e1,
    '1': 5fec8c55d967cf6260da05e2,
    '2': 5fec8c55d967cf6260da05e3
  }
}
```

無事にデータが作成されて、管理画面でも確認することができました。

管理画面の`COLLECTIONS`ボタンから確認できます。

> ![スクリーンショット 2020-12-30 23.20.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/aeb4e319-50dc-fd00-b707-0fff8d09de83.png "スクリーンショット 2020-12-30 23.20.53.png")

この辺はもう通常のMongoDBと使い方は変わらないです。
データ編集や削除はMongoDB公式やMongoDBのSDKなどの使い方を見ていけば大丈夫だと思います。

## まとめとよもやま(Realmの話など)

Node.jsからMongoDBを扱ったことがある前提があるからかもしれませんが、特に詰まることなく使い始めることが出来ました。

プロトタイピング的にデータベースをとりあえず使ってみるには向いてそうな気がします。

Firebaseなどは選択肢に上がると思いますが、Firebase用のコードになるのでその後裏側を変更しようとなったときに大変な気がします。

一方で、フロントエンドからのアクセスのAPIなどがあるわけではなさそうなので、これだけだとFirebase Cloud Firestoreの代替まではいかない気がします。ただ、MongoDB Atlasの管理画面からRealm DB(mBaaS)を作成することが出来るのですが、こちらを利用するとフロントエンドのブラウザSDKも使える模様です。（まだ試せて無い。）

> https://www.npmjs.com/package/mongodb-stitch-browser-sdk

ここまでくるとFirebase Cloud Firestoreの代替として使えるかも。

Realm、最近ウォッチしてなかったですがMongoDBに買収されてたんですねぇ、そしてネイティブアプリ開発界のモノだと思ってましたが、MongoDBの一部と考えるとWeb開発者もウォッチして良さそう。

Mongo DB Atlasで作り始めるとMongo DBのナレッジなども流用できるし、スケールさせたい場合も正式なMongoDBに差し替えるみたいな選択が出来るので、コードレベルでの変更が少なくすみそうです。