---
# System prepended metadata

title: MongoDB
tags: [NoSQL, MongoDB]

---

# 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`