Web3.0検証(13)-MeteorでTODO管理アプリの開発(MongoDBにデータ保存)

##### [前回] [Web3.0検証(12)-MeteorでTODO管理アプリの開発(基本機能)](https://qiita.com/mingchun_zhao/items/9c4cd4cf91d5bbc88e1e)

## はじめに

前回検証に続き、TODO管理アプリを機能拡張し、
MongoDBデータベースにTODOデータを保存します。

## MongoDBの基本

- MongoDBとは
    - ドキュメント指向のNoSQLデータベース
        - リレーショナルデータベース(RDB)と異なりトランザクションが無い
        - 大量データを高速処理できるメリット

- 構成要素の比較

|RDB|MongoDB|
|:--:|:--:|
|Database|Database|
|Table|Collection|
|Record|Document|
|Column|Field|

## 端末1から、Meteorアプリを実行
```
$ cd simple-todos-react
$ meteor run
[[[[[ ~/simple-todos-react ]]]]]

=> Started proxy.
=> Started HMR server.
=> Started MongoDB.
=> Started your app.

=> App running at: http://localhost:3000/
```

起動メッセージから、MongoDB起動を確認できます。

## 端末2から、MongoDBのコレクションを作成

API関連コード(メソッドなど)の保存場所`imports/api`ディレクトリにファイル追加。

```
$ cd simple-todos-react
$ vi imports/api/TasksCollection.js
```
```imports/api/TasksCollection.js
import { Mongo } from 'meteor/mongo';

export const TasksCollection = new Mongo.Collection('tasks');
```

新しいMongoコレクションをインスタンス化し、エクスポート。

不要ファイル`links.js`を削除
```
$ rm imports/api/links.js
```

## タスクコレクションの初期化

コレクションを機能させるため、コレクションをサーバーにインポート。
下記ファイルを上書きし、コレクションのデータ確認/挿入を行う。

```server/main.js
import { Meteor } from 'meteor/meteor';
import { TasksCollection } from '/imports/api/TasksCollection';

const insertTask = taskText => TasksCollection.insert({ text: taskText });

Meteor.startup(() => {
  if (TasksCollection.find().count() === 0) {
    [
      'First Task',
      'Second Task',
      'Third Task',
      'Fourth Task',
      'Fifth Task',
      'Sixth Task',
      'Seventh Task'
    ].forEach(insertTask)
  }
});
```

- ぶち解説
    - TasksCollectionをインポート
    - タスクを追加
    - 文字列配列を反復処理
        - 各文字列に対し`insertTask`関数を呼び出し
        - 文字列をタスクドキュメントのテキストフィールドとして挿入

## タスクコレクションをレンダリング

### Meteorパッケージの前提知識

- Meteorは、通常MeteorパッケージとNPMパッケージにより動作
    - パッケージは、Meteor内部または外部のものを利用可能
- `react-meteor-data`パッケージ
    - `react-meteor-data`パッケージはデフォルトで有効
    - 存在しない場合、`meteor add react-meteor-data`で追加
- Meteorパッケージからコードのインポート
    - npmモジュールとの唯一の違いは、インポートの`from`部分に`meteor/`を追加

### Reactフックの前提知識
- Reactフックとは
    - 関数コンポーネントにReactの機能(stateやライフサイクル)を接続するための関数
    - フックはReactをクラスなしに使うための機能で、クラス内では機能しない
- Reactフック`useTracker`
    - `useTracker`フックは、`react-meteor-data`によりエクスポートされる
    - ReactフックによりReactコンポーネントに反応性(reactivity)を持たせる
        - 反応性によって、データが変化されると、コンポーネントが即再レンダリングされる

### タスクのレンダリングに必要なもの

- React関数コンポーネント
- Meteor`react-meteor-data`パッケージ

```imports/ui/App.jsx
import React from 'react';
import { useTracker } from 'meteor/react-meteor-data';
import { TasksCollection } from '/imports/api/TasksCollection';
import { Task } from './Task';

export const App = () => {
  const tasks = useTracker(() => TasksCollection.find({}).fetch());

  return (
    <div>
      <h1>Welcome to Meteor!</h1>

      <ul>
        { tasks.map(task => <Task key={ task._id } task={ task }/>) }
      </ul>
    </div>
  );
};
```

## ブラウザでアプリを確認

ブラウザから、`http://localhost:3000/`にアクセス。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523098/5d8aa3b7-6ea2-a79a-a933-3a86e9d1abc5.png)|
|:--|

## MongoDBでデータ確認/変更

MongoDBでデータ確認します。
データ変更した場合は、アプリが反応し、再レンダリングしてくれます。

### 端末3から、MongoDBに接続

プロジェクトディレクトリに移動し、
`meteor mongo`コマンドでクライアント実行。
※ 内蔵されたMongoDBはポート番号3001で起動されます
※ 別のMongo UIクライアントツール`NoSQLBooster`も使用可

```
$ cd simple-todos-react/
$ meteor mongo
MongoDB shell version v5.0.5
connecting to: mongodb://127.0.0.1:3001/meteor?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("9b432a0c-1289-4841-bae7-b0fa70307d48") }
MongoDB server version: 5.0.5
... ...
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
        https://docs.mongodb.com/
Questions? Try the MongoDB Developer Community Forums
        https://community.mongodb.com
---
meteor:PRIMARY>
```

### データベース/コレクション/ドキュメントを確認

- データベース一覧
```
meteor:PRIMARY> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
meteor  0.000GB
```
- データベース`meteor`を指定
```
meteor:PRIMARY> use meteor
switched to db meteor
```
- コレクションを確認
```
meteor:PRIMARY> show collections
links
tasks
```
- ドキュメントを確認
```
meteor:PRIMARY> db.tasks.find()
{ "_id" : "kyMgiSuojrtJN2Ypt", "text" : "First Task" }
{ "_id" : "NzrbdgDkjfopMhvTG", "text" : "Second Task" }
{ "_id" : "bo2Lmn8pYdc7SNnsJ", "text" : "Third Task" }
{ "_id" : "wtzuHKhyxdvkp6PaG", "text" : "Fourth Task" }
{ "_id" : "Eg3nK2PkAfC8p2ckJ", "text" : "Fifth Task" }
{ "_id" : "C5XCHP9QRN8HwopNa", "text" : "Sixth Task" }
{ "_id" : "Lz97hBMpqtTC57xEf", "text" : "Seventh Task" }
```

TODO管理アプリのデータがMongoDBに保存されていることを確認できました。
ただし、2点課題が存在します。
- 課題1: データはどうやってサーバーからクライアント送られたの?
  - その仕組みは、以下機能2点と関係するようです(詳細は次回)
    - Publications(パブリケーション)
    - Subscriptions(サブスクリプション)
- 課題2: データベースのデータがクライアントに公開され丸見えだが大丈夫?
    - セキュリティ上よろしくないため、後で削除します

## おわりに

次回も、引き続きTODOアプリを改善していきます。
お楽しみに。

##### [次回] [Web3.0検証(14)-MeteorでTODO管理アプリの開発(新しいタスクの追加機能)](https://qiita.com/mingchun_zhao/items/7b9dcf05b166f3e2fe04)