mongoDB, mongooseを使ってCRUDを実装する

##CRUDとは

>CRUD（クラッド）とは、ほとんど全てのコンピュータソフトウェアが持つ永続性[1]の4つの基本機能のイニシャルを並べた用語。その4つとは、Create（生成）、Read（読み取り）、Update（更新）、Delete（削除）である。


(Wikipediaより)

<h6>・CRUDそれぞれに対応するHTTPメソッド</h6>
・Create:Postメソッド
・Read:Getメソッド
・Update:Patchメソッド
・Delete:Deleteメソッド

※CRUD処理の為にHTTPメソッドを実装した後は、ちゃんと動くか、Postmanを用いてテストすると良い。
＜参考＞『Postmanを使ってHTTPに送ったデータを確認する』（https://qiita.com/Molly95554907/items/e367e83129ea1173c317）

##CRUDの実装

```javascript
const express = require('express')
require('./db/mongoose')    　　　　　　　　//別ファイル（mongooseの読み込み）
const User = require('./models/user')　　//別ファイル（mongooseによるuserの定義の読み込み）

const app = express()
//process.env.PORTはherokuで動かす時のポート
const port = process.env.PORT || 3000

//HTTPへ送ったデータを情報の読み取れるようにする
app.use(express.json())

```

##Create
＜公式ドキュメント＞
・データをデータベースに送る

```javascript
app.post('/users', (req, res) => {
    const user = new User(req.body)　　//リクエストで送ったデータをUserインスタンスに入力

    user.save().then(() => {　　　　　//新しく作成したUserインスタンスをDBに保存
        res.status(201).send(user)　　//保存成功したら、HTTPステータス201と、保存したデータを返す
    }).catch((e) => {　　　　　　　　　//保存失敗したら、HTTPステータス400とエラーメッセージを返す
        res.status(400).send(e)
    })
})

```

＜非同期処理（Promise）を用いた実装＞

```javascript

app.post('/users', async (req, res) => {　　//asyncで処理した関数はPromiseを返す
    const user = new User(req.body)　　　　　//リクエストで送ったデータをUserインスタンスに入力

    try {　　　　　　　　　　　　　　//保存成功したら、HTTPステータス201と、保存したデータを返す
        await user.save()
        res.status(201).send(user)
    } catch (e) {
        res.status(400).send(e)　　　//保存失敗したら、HTTPステータス400とエラーメッセージを返す
    }
})
```

##Read
＜公式ドキュメント＞
・データをデータベースからとってくる

```javascript
app.get('/users', (req, res) => {
    User.find({}).then((users) => {　　　//find({})で全てのデータを取得
        res.send(users)　　　　　　　　　　//取得した全てのデータを返す
    }).catch((e) => {
        res.status(500).send()　　　　　　//取得失敗したら、HTTPステータス500を返す
    })
})

```

＜非同期処理（Promise）を用いた実装＞


```javascript

app.get('/users', async (req, res) => {
    try {
        const users = await User.find({})　　//find({})で全てのデータを取得
        res.send(users)　　　　　　　　　　　　　//取得した全てのデータを返す
    } catch (e) {
        res.status(500).send()　　　　　　　　　//取得失敗したら、HTTPステータス500を返す
    }
})

```

##Updaet
・データの更新
＜公式ドキュメント＞
「API > Model」の項目から探す。
・findById
https://mongoosejs.com/docs/api/model.html#model_Model.findById
・findByIdAndUpdate
https://mongoosejs.com/docs/api/model.html#model_Model.findByIdAndUpdate

```javascript

app.get('/users/:id', (req, res) => {
    const _id = req.params.id　　//「:id」に打ち込んだ値を取得

    User.findById(_id).then((user) => {　　//「:id」に打ち込んだIDと同じドキュメントを探す
        if (!user) {
            return res.status(404).send()　//「:id」に打ち込んだIDと同じドキュメントがなければ、HTTPステータス404を返す
        }

        res.send(user)　　//「:id」に打ち込んだIDと同じドキュメントが見つかればそれを返す
    }).catch((e) => {
        res.status(500).send()　　//取得失敗したら、HTTPステータス500を返す
    })
})

```

＜非同期処理（Promise）を用いた実装＞


```javascript

app.patch('/users/:id', async (req, res) => {
    const updates = Object.keys(req.body)  //リクエストで送った更新データを取得
    const allowedUpdates = ['name', 'email', 'password', 'age']  //updateできる項目を限定する
    const isValidOperation = updates.every((update) => allowedUpdates.includes(update))　　//リクエストで送った更新データがupdateできる項目に当てはまっているか

    if (!isValidOperation) {
        return res.status(400).send({ error: 'Invalid updates!' })　//当てはまっていなければ、HTTPステータス404とエラーメッセージを返す
    }

    try {
        const user = await User.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true })
    
        if (!user) {　　//「:id」に打ち込んだIDと同じドキュメントを探し、なければHTTPステータス404を返す
            return res.status(404).send()
        }

        res.send(user)　　　//「:id」に打ち込んだIDと同じドキュメントが見つかればそれアップデートし返す
    } catch (e) {
        res.status(500).send(e)　　//取得失敗したら、HTTPステータス500を返す
    }
})
```


##Delete
・データの削除
＜公式ドキュメント＞
findByIdAndDelete
https://mongoosejs.com/docs/api/model.html#model_Model.findOneAndDelete

```javascript
app.delete('/users/:id', async (req, res) => {
    try {
        const user = await User.findByIdAndDelete(req.params.id)  //「:id」に打ち込んだIDと同じドキュメントを探し削除

        if (!user) {
            return res.status(404).send()　　//「:id」に打ち込んだIDと同じドキュメントがなければHTTPステータス404を返す
        }

        res.send(user)　　　//「:id」に打ち込んだIDと同じドキュメントが見つかればそれを削除し返す
    } catch (e) {
        res.status(500).send()　　//取得失敗したら、HTTPステータス500を返す
    }
})

```