mongooseを使ってmongoDBを記述する

##mongooseとは
MongoDBを操作するためのnpmモジュール。
MongoDBのフィールドに様々な入力設定を行うことができる。

フィールドに挿入するデータ型を設定することができる。

##※MongoDBとMySQLの呼称の違い
<h6>MySQL</h6>
データは「テーブル」の形で保存される。
<img width="651" alt="スクリーンショット 2020-06-21 17.04.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595580/ec37c8a3-ec02-7dc3-2542-93e52b5673b7.png">

・列（column）
　<img width="135" alt="スクリーンショット 2020-06-21 17.05.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595580/c700ffc1-c484-3fb8-fef2-60c851394f41.png">

・行（row）
<img width="656" alt="スクリーンショット 2020-06-21 17.06.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595580/5b79fba0-1f29-c62c-c787-90047b84eae1.png">

<h6>MongoDB(NoSQL)</h6>
データは「コレクション」の形で保存される
<img width="505" alt="スクリーンショット 2020-06-21 17.07.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595580/1055f096-035a-c34a-5250-c16bc62df9ed.png">

・フィールド（列に対応）
<img width="339" alt="スクリーンショット 2020-06-21 17.09.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595580/81fe986c-a052-f3a9-1947-f569653280e0.png">


・ドキュメント（行に対応）
<img width="367" alt="スクリーンショット 2020-06-21 17.08.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595580/9ba6a521-0114-af37-6a5a-e55e1a3ec5c3.png">


<h6>・アプリ作成時のファイル構成例</h6>

```
└── src
    ├── db
    │   └── mongoose.js     //mongooseのnpmモジュールを読み込み
    ├── index.js           //アプリのメイン処理を記述
    ├── models
    │   ├── task.js　       //taskデータベースのためのフィールド設定
    │   └── user.js　      //userデータベースのためのフィールド設定
    └── routers
        ├── task.js　      //express・taskデータベース操作のためのルーティング処理
        └── user.js       //express・userデータベース操作のためのルーティング処理

```
##mongooseの読み込み

・「npmパッケージ『mongoose』、公式ドキュメント」を参照
https://www.npmjs.com/package/mongoose

プロジェクトファイルに、「npm i mongoose」でmongooseをインストール

・mongooseを読み込む

「mongooseの公式ドキュメント」( https://mongoosejs.com/ )を参照し、読み込みのためのコードを記述。

＜mongoose.js＞

```javascript

const mongoose = require('mongoose')

//mongodbのポートの読み込みと、mongoDBのコレクション名(task-manager-api)をつける
mongoose.connect('mongodb://localhost:27017/task-manager-api', {
  useNewUrlParser: true, 
  useUnifiedTopology: true,
  useFindAndModify: false
});
```

＜参考＞「mongooseの公式ドキュメント」( https://mongoosejs.com/ )のコード

```javascript

//mongooseモジュールの読み込み
const mongoose = require('mongoose');
//mongodbのポートの読み込みと、mongoDBのコレクション名(test)をつける
mongoose.connect('mongodb://localhost:27017/test', {useNewUrlParser: true, useUnifiedTopology: true});

//const Cat:Catというドキュメントを作成
//'Cat':データモデルの名前
//nameフィールドのデータ型をStringに設定。
const Cat = mongoose.model('Cat', { name: String });

//"Cat"データモデルの新しいインスタンスを作成。
//kittyというドキュメントで、nameは'Zildjian'
const kitty = new Cat({ name: 'Zildjian' });

//kittyドキュメントをデータベースに保存する。保存できたら"meow"と表示させる
kitty.save().then(() => console.log('meow'));
```

##mongooseで挿入するデータ型を設定する
<h6>・入力するデータ型を設定</h6>
＜公式ドキュメント＞
"Schemas"を参照( https://mongoosejs.com/docs/guide.html#statics )

<img width="426" alt="スクリーンショット 2020-06-21 17.28.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595580/2fbb7419-a11d-6002-cbf0-254e0d71e359.png">

＜例＞

```javascript
const Cat = mongoose.model('Cat', { 
  name: {
     type: String  //データ型は文字列
},
  age: {
     type: Number　//データ型は数字
},
  isMine: {
     type: Boolean  //データ型はtrueかfalseのどちらか
}
});

```

<h6>・入力するデータ形式を自作・最小値/最大値の設定・入力必須設定・エラー設定</h6>
＜公式ドキュメント＞
"Validation"を参照（ https://mongoosejs.com/docs/validation.html#built-in-validators )

<h6>・小文字として認識・空白スペースの削除（データサニタイズ）</h6>

```javascript
const User = mongoose.model('User', {
  password:{
    type: String,
    required: true,  //入力必須設定
    trim: true,　　//空白を無くして認識
    minlength: 7,　//最小入力文字数設定

　　//validate(value:入力した値)で、入力するデータ形式を自作
    validate(value){
     　 //toLowerCaseで、小文字も大文字も小文字と認識する設定
      if(value.toLowerCase().includes('password')){

　　　　//エラーを起こして処理を分岐させる
        throw new Error ('Do not use "password" to password')
      }
    }
  }
```
<h6>・デフォルトの入力を設定</h6>

```javascript
const Task = mongoose.model('Task', {
  complete:{
    type: Boolean,
    default: false,  //デフォルトの入力値を設定
  }
})
```
<h6>・データベースに入力す値を一意に設定</h6>

```javascript
email: {
    type: String,
    unique: true, //データベース上のemailの値を一意にする›
    required: true,
    trim: true,
    lowercase: true,
    validate(value){
      if(!validator.isEmail(value)){
        throw new Error ('Email is invalid')　//npmパッケージ、「validator」を利用し、メールアドレスとして正しい値か確認
      }
    }
  },
```