# MongoDB
## MongoDBとは
MongoDBはクロスプラットフォーム対応のオープンソースドキュメントDBである。
NoSQLでは最有力のDBである。
### MongoDBの特徴
* データ形式:JSONドキュメントのコレクション
* データ容量:RDBMSよりも大容量
* データの整合性:満たさない。(結果整合性=トランザクション処理不可)
* データの可用性:満たす。
* データの分断耐性:満たす。
* データの結合(JOIN):不可。
* 得意とする処理:JSON形式ドキュメントの保存
以上から、MongoDBは高速・大容量なJSONドキュメント保存に適する。
### MongoDBを利用した方が良い場面
* データの整合性よりも速度を求める場合。
* データの耐障害性を高めたい場合。
* スキーマを事前に定義できない場合。(JSONの保存等)
## MongoDBとRDBMSのスキーマの違い
### RDBMS
基本的な考え方は、第3正規形を満たしながら2つのテーブルに分ける。
(例)パスポート
**人物マスタ**
人物id(PK)
氏名
**パスポートマスタ**
パスポートid(PK)
人物id(FK)
国名
有効期限
☆実行結果
mysql> select * from people;
+----+------------+
| id | name |
+----+------------+
| 1 | Stephane |
| 2 | John |
| 3 | Michael |
| 4 | Cinderella |
+----+------------+
mysql> select * from passports;
+----+-----------+---------+-------------+
| id | people_id | country | valid_until |
+----+-----------+---------+-------------+
| 4 | 1 | FR | 2020-01-01 |
| 5 | 2 | US | 2020-01-01 |
| 6 | 3 | RU | 2020-01-01 |
+----+-----------+---------+-------------+
### MongoDB
MongoDBはスキーマレスのため、形式は自由である。
第3正規形を使うと、必ずJOIN処理が発生してしまうため、非効率。
そこで以下の方法が考えられる。
#### 全てのデータを一括保存
> db.people_all.find().pretty()
```json=
//Staphaneさん
{
"_id" : ObjectId("51f7be1cd6189a56c399d3bf"),
"name" : "Stephane",
"country" : "FR",
"valid_until" : ISODate("2019-12-31T23:00:00Z")
}
//Johnさん
{
"_id" : ObjectId("51f7be3fd6189a56c399d3c0"),
"name" : "John",
"country" : "US",
"valid_until" : ISODate("2019-12-31T23:00:00Z")
}
//Michaelさん
{
"_id" : ObjectId("51f7be4dd6189a56c399d3c1"),
"name" : "Michael",
"country" : "RU",
"valid_until" : ISODate("2019-12-31T23:00:00Z")
}
//Cinderellaさん(架空→パスポート無し)
{
"_id" : ObjectId("51f7be5cd6189a56c399d3c2"),
"name" : "Cinderella",
}
```
特徴
* 同一構造でないドキュメントも一括保存可能である。
* どの要素がパスポートについてで、どの要素が人物についてなのかが分かりにくくなる。
#### 人物情報の中にパスポート情報を埋め込む
あらかじめパスポート情報のドキュメントを埋め込んでおき、どの要素がどちらの要素であるかをはっきりさせる。
```json=
//Staphaneさん
{
"_id" : ObjectId("51f7be1cd6189a56c399d3bf"),
"name" : "Stephane",
"passport" : {
"country" : "FR",
"valid_until" : ISODate("2019-12-31T23:00:00Z")
}
}
//Johnさん
{
"_id" : ObjectId("51f7be3fd6189a56c399d3c0"),
"name" : "John",
"passport" : {
"country" : "US",
"valid_until" : ISODate("2019-12-31T23:00:00Z")
}
//Michaelさん
{
"_id" : ObjectId("51f7be4dd6189a56c399d3c1"),
"name" : "Michael",
"passport" : {
"country" : "RU",
"valid_until" :ISODate("2019-12-31T23:00:00Z")
}
}
//Cinderellaさん(架空→パスポート無し)
{
"_id" : ObjectId("51f7be5cd6189a56c399d3c2"),
"name" : "Cinderella",
}
```
### スキーマまとめ
MongoDBは、保存形式を問わないため、アプリケーションが最もよくアクセスするパターンを念頭にデザインする。
RDBMSでは、アクセスするパターンよりも、正規化されているかどうかを念頭にデザインする。
## 参照ページ
[世界第4位!最有力NoSQLデータベースMongoDBはRDBとどう違うのか?特徴と使い分け](https://tracpath.com/works/development/nosql_mongodb/)
###### tags: `NoSQL`, `MongoDB`