Express(Node.js)とMongoDBで人物プロフィールを登録・取得するAPIの作成

## はじめに
Node.jsのフレームワークのExpressを用いて、人物のプロフィールを登録・取得できるREST APIを作成します。
データベースはMongoDBを使用します。

## 環境
- CentOS 7.5
- Node.js 6.14.3
- Express 4.16.0
- MongoDB 3.6.7

## 準備
コードを書く前に必要なものをインストール・設定します。

### Node.jsインストール
まず[Node.js](https://nodejs.org/ja/download/package-manager/)をインストールします。

```
# yum install nodejs npm --enablerepo=epel
```

new_projectという名前のプロジェクトをつくります。

```
# mkdir new_project
# cd new_project
```

npm initでpackage.jsonを作成します。
対話形式で作成されるので自分のプロジェクトに合わせた内容にします。

```
# npm init
```

### ファイアウォールの設定

3000番ポートを開放します。

```
# firewall-cmd --add-port=3000/tcp --zone=public --permanent
success
# firewall-cmd --reload
success
```

### Expressをインストール
次に[Express](https://expressjs.com/ja/starter/installing.html)をインストールします。

```
# npm install express --save
```

### MongoDB Node.JS Driverをインストール
MongoDBをNode.jsで利用するために[MongoDB Node.JS Driver](https://mongodb.github.io/node-mongodb-native/)をインストールします。

```
# npm install --save mongodb
```

MongoDBをインストールしていない場合は、[公式のドキュメント](https://docs.mongodb.com/manual/administration/install-community/)に従って、自分の環境に合わせたものをインストールしてください。

### データベースの準備
mongoシェルでデータベース(mydb)とコレクション(person)の作成を行います。

mongoシェル起動

```
# mongo
```

データベース作成

```
> use mydb
switched to db mydb
```

この段階でshow dbsをしてもコレクションを作っていないのでdb一覧には表示されません。

コレクション作成

```
> db.createCollection('person');
{ "ok" : 1 }
> show collections
person
```

## API作成
POSTメソッドで名前と年齢を送信し、データベースに追加します。
GETメソッドで登録した人物の年齢を取得します。


``` js:app.js
const express = require("express");
const app = express();
// 待ち受け
const server = app.listen(3000, function(){
    console.log("Node.js is listening to PORT:" + server.address().port);
});

// mongodb読み込み
const MongoClient = require("mongodb").MongoClient;
// 接続文字列
const dbUrl = "mongodb://localhost:27017/";
// データベース名
const dbName = 'mydb';

// postの処理
app.post("/api/test", (req, res) => {

  // MongoDBへ接続
  MongoClient.connect(dbUrl, {
    useNewUrlParser: true
  }, (err, client) => {

    // コレクションの取得
    const col = client.db(dbName).collection('person');

    // コレクションにドキュメントを挿入
    col.insertOne({
      name: req.body.name, // POSTで送られてきたパラメータを取得
      age: req.body.age
    }, (error, result) => {
      client.close();
    });
  });
  res.send('POSTdata is sended.');
});

// getの処理
app.get("/api/test", (req, res) => {

  // MongoDBへ接続
  MongoClient.connect(dbUrl, {
    useNewUrlParser: true
  }, (err, client) => {

    // コレクションの取得
    const col = client.db(dbName).collection('person');

    // ドキュメント取得
    col.find({
      name: req.query.name
    }).toArray((error, documents) => {
      for (let document of documents) {
        res.send(document.age);
        client.close();
      }
    });
  });
});

```



ここでuseNewUrlParser: trueを指定していないと以下のwarningがでます。
現在のparserが将来非推奨になるとのことです。

> (node:15513) DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.

参考：https://thanhphu.net/blog/2018/05/23/about-mongos-usenewurlparser-warning/


## 実際に動かしてみます
サーバを起動します。

```
# node app.js
Node.js is listening to PORT:3000
```

### オプション
app.jsファイルの変更内容を反映させるためには、その都度サーバを再起動しなければなりません。
ですので[nodemon](https://nodemon.io/)と呼ばれるパッケージをインストールしておくことをお勧めします。

```
# npm install -g nodemon

/* nodemon起動(# node app.jsの代わりに使います) */
# nodemon start
[nodemon] 1.18.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node start app.js`
Node.js is listening to PORT:3000
[nodemon] restarting due to changes... // 変更があれば自動で再起動
[nodemon] starting `node start app.js`
Node.js is listening to PORT:3000

```

### curlでPOSTする
山田さん20歳を登録してみます。

```
curl http://xxx.xxx.xxx.xxx:3000/api/test -X POST -d "name=Yamada&age=20"
```

ここでPOSTすると以下のエラーがでます。

> TypeError: Cannot read property 'name' of undefined

これを解決するためにbody-perserを入れます。
https://qiita.com/K_ichi/items/c70bf4b08467717460d5


```
# npm install --save body-parser
```

app.jsに以下のコードを追加します。

``` js:app.js
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: true}));
```

もう一度curlを実行するとPOSTが成功します。
mongoシェルを確認してみます。

```
> db.person.find();
{ "_id" : ObjectId("5b92375d7ab8243cdae7711e"), "name" : "Yamada", "age" : 20 }
```

ちゃんとドキュメントが追加されました。

### curlでGETする
次はGETで山田さんの年齢を取得してみます。

```
curl http://xxx.xxx.xxx.xxx:3000/api/test?name=Yamada
20
```

年齢取得できました。


## 参考
[Node.js+Express+MongoDBでREST APIをつくる](https://qiita.com/itagakishintaro/items/a1519998a91061cbfb1e)