VisualStudio CodeからMongoDBにつなげてみよう！

## はじめに

この記事は、[Visual Studio Code Advent Calendar 2020](https://qiita.com/advent-calendar/2020/vscode) の11日目の記事になります。
今回は、表題の通り[MongoDB for VS Code](https://www.mongodb.com/products/vs-code)を使ってMongoDBに接続してみるというお話です。(※VisualStudio Code は、以下VSCodeと記載します）

### ところでなぜMongoDB?

ただいま個人学習として、MondoDB公式が提供している、[MongoDB University](https://university.mongodb.com)というオンライン学習コースをコツコツ進めています。[^1][^2]

MongoDBのクライアントとしては、[MongoDB Compass](https://www.mongodb.com/products/compass)という非常に優れたツールがあります。ただ、コーディングしながらであれば、データの簡単な確認はエディタ内で済ませたい...。
また、コースが進むにつれ、APIのみでの操作でなく、MongoDBのプロセスや運用面のトピックも出てきたので、もう少しデータファイルなども見える方が良い。

幸い、Dockerの公式イメージもあるので、ローカル開発環境での起動にはDockerが使えます。このあたりを踏まえて、「**全部VSCode内で完結するかしら？**」と思ってやってみた顛末となります。

## まずはMongoDBのDockerイメージを使おう！

実のところ、MongoDB Atlasというクラウドのサービスを使えば、無償枠でもサービスとしてはMondoDBの操作が可能なので、MongoDB Extensionを試すのにはローカルでDockerのMongoDBを起動する必要はありません。

ただし、上記の通り、プロセスやデータファイルの管理の仕方も合わせて確認したいので、Dockerで起動してみることにします。

### 公式のイメージから起動するよ！

イメージは、こちらを使います。

- https://hub.docker.com/_/mongo

VSCodeのDocker Extensionも非常に便利で日々進化していて、これがないとわたしはお仕事ができません...。[^3]
わたしの環境はMacですので、DockerのホストとしてはDocker for Macを利用します。

```bash
# まずはイメージを引っ張ってきます
docker pull mongo
```

イメージを取得後、VSCodeのDocker Extensionを使うと、Dockerイメージの一覧や起動中のコンテナが表示できます。
MondoDBのイメージは、そのままVSCodeから右クリックで起動ができます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27976/955168d1-857e-23a4-fa4b-849f826cbd64.png" width="400">

コンテナが立ち上がると、上部にMongoDBのコンテナが表示されます。
ここからさらに右クリックで起動中のコンテナ内にアクセスしたり、ログを確認することができます。
コンテナ内のファイルシステムも、VSCodeから表示できるようになっています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27976/9e15169b-7e8a-a811-9a89-455b5c1fc94b.png" width="500">

### コンテナ内に入ってMongo Shellを利用してみよう！

VSCodeのコンテナの表示から、右クリックでコンテナにアタッチします。(Attach Shellで、実際は docker execコマンドが走ります)

MondoDBの公式イメージは、シェルにアクセスできるので、コンテナ内でpsコマンドでMondoDBのプロセスが上がっていることを確認してみました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27976/e8745884-cd2f-c90a-cc84-1f60fefb51a3.png" width="500">

内部には、もちろん[MongoDB Shell](https://www.mongodb.com/products/shell) (データベースにアクセスするためのCUIのクライアント）が入っているので、単純に ``mongo`` コマンドを打つだけで、操作が可能になります。

ちょっと長いですが、コンテナ内での結果を貼ってみます。

```bash
# mongoコマンドで起動（内部からでパスワード無し）
root@b0c9ee280d35:/# mongo
MongoDB shell version v4.4.2
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("fec4ef7e-b4b4-4b55-937c-1ccf82510de9") }
MongoDB server version: 4.4.2
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
        https://docs.mongodb.com/

...[一部略]...

---
> show databases
admin   0.000GB
config  0.000GB
local   0.000GB
test    0.000GB
> use test
switched to db test
> show collections
sales

> db.sales.findOne()
{
        "_id" : 1,
        "item" : "abc",
        "price" : 10,
        "quantity" : 2,
        "date" : ISODate("2014-03-01T08:00:00Z")
}
```

データベースの一覧表示と、test DBへの切り替えができました。

また、デフォルトで /data/db 以下にあるデータファイルも見てみます。

```bash
root@b0c9ee280d35:/data/db# pwd
/data/db
root@b0c9ee280d35:/data/db# ls -w 1
WiredTiger
WiredTiger.lock
WiredTiger.turtle
WiredTiger.wt
WiredTigerHS.wt
_mdb_catalog.wt
collection-0--359143437334718796.wt
collection-13--359143437334718796.wt
collection-2--359143437334718796.wt
collection-4--359143437334718796.wt
diagnostic.data
index-1--359143437334718796.wt
index-14--359143437334718796.wt
index-3--359143437334718796.wt
index-5--359143437334718796.wt
index-6--359143437334718796.wt
journal
mongod.lock
sizeStorer.wt
storage.bson
```

MongoDBのストレージエンジンはWiredTigerを使っているので、``WiredTiger.*``なファイルがあるのが確認できました。
コレクション（データベースに相当）するファイル、インデックスファイルは、拡張子が ``.wt`` になっています。

Docker Extensionは便利ですね！

## MongoDB for VS Codeを使ってみよう！

長くなりましたが、ここからが本題です。
まずは拡張機能のメニューから、MongoDBと検索し、追加してみましょう。
20201211時点では、プレビュー版となっていますが、それでもだいぶいろんなことができます！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27976/23e668c5-d592-4b11-4b3f-2ed7eb068a28.png" width="500">

20201211時点での機能は、以下の通り。

- MongoDB Atlas、もしくは任意のMondoDBに接続ができる
  - コレクション（テーブルに相当）の表示
  - スキーマの表示
  - ドキュメント（レコードに相当）の表示 
- MongoDB Playgrounds という機能で、**エディタ上に記載したMongoDB用のクエリを実行**し、データの追加や検索、アグリゲーションの操作ができる
- MongoDB Shellの起動ができる[^4]
- Terraformを使って、MondoDB Atlas上のデータベースの構成を管理できる

GitHub上の[Issue](https://github.com/mongodb-js/vscode/issues) (Feature)もたくさんあって、今後ますます楽しみです！

### まずは接続をしてみよう！

Dockerで起動したMongoDBは、特に指定がなくても以下のコマンドで起動してくれるので、Mac側にポート27017がフォワードされるため、localhost:27017を介して接続できるようになります。

```bash
docker run --rm -d  -p 27017:27017/tcp mongo:latest
```

拡張機能を追加すると、葉っぱのマークが左のバーに表示されるので、そこからMongoDB操作用のパネルに切り替えができます。

接続設定を行うため、Connectionsのメニューから右クリックで **Add MongoDB Connection** を選ぶと、接続設定用の画面が表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27976/36037d97-fbf3-61e9-ea0b-f580a0aa1f55.png" width="500">

単純に起動した場合は、**パスワードは設定無しの状態で起動します**ので、接続設定には、以下を記載してボタンを押せばOKです。[^5]

- Hostname: localhost
- Port: 27017

※PCやご利用の環境でファイアウォールやセキュリティソフトがPort 27017の通信をブロックしていると、正しく接続できないのでご注意を！

うまくいくと、左側にデータベースの一覧が表示されます。
まだ管理用のものしかありません。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27976/d7bd412e-903f-62bf-78c4-83d2c982281f.png" width="500">

各データベースをクリックすると、テーブルに相当するコレクションが表示されます。
次々とクリックしていくと、さらにインデックスやスキーマ、データも表示できます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27976/32566377-3664-3b5b-4a2e-8c6c9e4c2b01.png" width="500">

## MongoDB Playgroundsを使ってデータベースを作成してみよう！

おそらく何らかのデータベース用のGUIクライアントを使ったことがある方は、あとは直感的に操作がわかると思います。

さて、管理用のデータベースだけでは困るので、データベースの作成をしてみたい。
MongoDB Shellを使ってデータベース作成もできますが、この拡張機能には、**MongoDB Playgrounds** という機能があります。

操作パネルの下の方に、**Create New Playgrounds**というボタンがあるのでクリックすると、MongoDB操作用のサンプルスクリプトが書かれた画面が表示されます。
この言語はMQL(MongoDB Query Language)と言われるものです。[^6]

この画面には、こんな内容が書かれています。
内容は、こんな感じ。

- 任意のデータベース（ここでは``mongodbVSCodePlaygroundDB``）に接続
- データベースの``sales``というコレクションにデータを追加
    - ちなみに、デフォルトではコレクションが存在しない場合は、勝手に作成されます
- データ登録後、find() クエリで検索を実行します
- aggregationを使って、検索＆集計をします

```JavaScript
// Select the database to use.
use('mongodbVSCodePlaygroundDB');

// Insert a few documents into the sales collection.
db.sales.insertMany([
  { '_id' : 1, 'item' : 'abc', 'price' : 10, 'quantity' : 2, 'date' : new Date('2014-03-01T08:00:00Z') },
  { '_id' : 2, 'item' : 'jkl', 'price' : 20, 'quantity' : 1, 'date' : new Date('2014-03-01T09:00:00Z') },
  { '_id' : 3, 'item' : 'xyz', 'price' : 5, 'quantity' : 10, 'date' : new Date('2014-03-15T09:00:00Z') },
  { '_id' : 4, 'item' : 'xyz', 'price' : 5, 'quantity' :  20, 'date' : new Date('2014-04-04T11:21:39.736Z') },
  { '_id' : 5, 'item' : 'abc', 'price' : 10, 'quantity' : 10, 'date' : new Date('2014-04-04T21:23:13.331Z') },
  { '_id' : 6, 'item' : 'def', 'price' : 7.5, 'quantity': 5, 'date' : new Date('2015-06-04T05:08:13Z') },
  { '_id' : 7, 'item' : 'def', 'price' : 7.5, 'quantity': 10, 'date' : new Date('2015-09-10T08:43:00Z') },
  { '_id' : 8, 'item' : 'abc', 'price' : 10, 'quantity' : 5, 'date' : new Date('2016-02-06T20:20:13Z') },
]);

// Run a find command to view items sold on April 4th, 2014.
db.sales.find({ date: { $gte: new Date('2014-04-04'), $lt: new Date('2014-04-05') } });

// Run an aggregation to view total sales for each product in 2014.
const aggregation = [
  { $match: { date: { $gte: new Date('2014-01-01'), $lt: new Date('2015-01-01') } } },
  { $group: { _id : '$item', totalSaleAmount: { $sum: { $multiply: [ '$price', '$quantity' ] } } } }
];
db.sales.aggregate(aggregation);
```

この内容を、直にMongoDB Shellに貼り付けても同じことはできますが、MongoDB Playgroundsを使うと、画面上部に▶︎の実行マークが表示され、そのマークを押すと、MongoDBに対し上記の処理が実行されます。

または、実行したい箇所（行）単位を選択すると、うっすらと▶︎の実行マークが表示され、その箇所だけが実行されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27976/8fc72bcd-ca6f-cf0c-9f09-f50b644936cb.png" width="500">

Playgroundのパネル上の処理を実行後、MongoDBの操作パネル側からデータを確認すると、salesというデータベースが作成され、8件追加されたのがわかります。

また、選択箇所単位での実行が可能で、実行結果は別パネルに表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27976/dc979628-6330-0804-de65-3ce16b147138.png" width="500">


このPlaygroundのパネル上の内容は書き換えた上での実行が可能なので、MongoDB Shellを使わずに、複雑なクエリを投げたい場合には特に重宝すると思います。

## まとめ

以上、ざっくりと機能紹介をさせていただきました。

MongoDB for VS Codeの操作パネルの下側には、ドキュメントへのリンクや、GitHub Issueへのリンク、それからMongoDB Atlas上にクラスタを作るショートカットも用意されています。

まだまだ開発途上なので、もう少し使い倒して、なにかフィードバックできたらなと思っています。

今回は合わせてDocker Extensionについても触れています。
Dockerの技術は日々進歩していて、大規模な管理の仕組みはわたしは全く追いつけていないのですが、イメージやコンテナの基本操作は、GUIの力を借りて確認しながら覚えていけます。
アプリケーション開発に取り組む方は、ぜひVSCodeと合わせて使ってみてくださいね！



[^1]: MongoDBの基本を学習できるオンラインでの学習コースです。基本コースから開発者、管理者向けにコースがわかれていき、データモデリングやセキュリティ、デバッグといった範囲も扱います。
[^2]: 「[ひとりMongoDB University](https://adventar.org/calendars/5177)」と題して学習記録を付けています。
[^3]: いまや、Dockerコンテナの中に入って直にVSCodeでコンテナ内のファイルが編集できるようになっています。(https://code.visualstudio.com/docs/remote/containers)
[^4]: ローカルのMondoDB Shell (mongosh) を呼び出してくれます。このため、mongoshのインストールとVSCodeへのパスの追加が必要です。
[^5]: 実運用ではこの状態はよろしくないので、``authentication is enabled`` なモードで起動をしましょう...。
[^6]: https://developer.mongodb.com/how-to/getting-started-atlas-mongodb-query-language-mql に、このPlaygroundでMQLを利用する方法が詳細に紹介されています。（英語）