MongoDBのスキーマ設計入門

MongoDB

cover image from Unsplash

Photo by Kwang Javier on Unsplash

本記事について

MongoDB をはじめて触る人を対象とした MongoDB におけるドキュメントの構造とスキーマ設計の考え方。

参考

 

はじめに用語解説

docment

RDB における record に相当。
JSON Object とほぼ同じ形式。

collection

RDB における table に相当。
collection 内の docment は、デフォルトで同じフィールドや同じデータ型を持つ必要がない。

Scheme Validation を使用すると、許可されるデータ型や値の範囲などの制約を設定できる。

field

RDB における column に相当。

Atomicity

「トランザクション内のすべての操作が完了する」か、「すべて失敗する」かのどちらかしかないということを保証する。
トランザクションを定義する 4 つの重要な特性、Atomicity(原子性)、Consistency(一貫性)、Isolation(独立性)、Durability(永続性)のうちの一つ。

 

2 種類の document 構造

スキーマ設計をするにあたり、document の構造をどうするか、データ間の関係をどう示すかは以下の二つから選択することになる。

1. Embedded Data Models(denormalized)

以下の例では、ブログ記事の情報に加えて、記事の著者(author)とコメント(comments)も埋め込まれている。

// article collection
{
  "_id": "1234567890",
  "title": "My Blog Post",
  "body": "This is my blog post.",
  "author": {
    // embedded
    "name": "John Smith",
    "email": "john.smith@example.com"
  },
  "comments": [
    // embedded
    {
      "name": "Jane Doe",
      "email": "jane.doe@example.com",
      "body": "Great post!"
    },
    {
      "name": "Bob Johnson",
      "email": "bob.johnson@example.com",
      "body": "Thanks for sharing."
    }
  ]
}

Embedded Data Models は、一回の DB 操作で関連データを取得できるという利点がある。

大抵のケースでは、このモデルが適しているらしい。
ただし、document にはデータサイズの上限がある点には注意。

2. Normalized Data Models

正規化もできる。

以下の例では、著者とコメントは別のコレクションに格納されている。

// user collection
{
  "_id": "1234567890",
  "name": "John Smith",
  "email": "john.smith@example.com"
}
 
// order collection
{
  "_id": "0987654321",
  "user_id": "1234567890",      // user collection id
  "item": "MongoDB in Action",
  "price": 29.99
}

 

Atomicity が保証される範囲に注意

単一 document の操作は、atomicity が保たれている。

複数 document にまたがる操作は、atomic ではない。 この場合、各 document の更新は atomic だが操作全体は atomic ではない。

なお、現在では multi-document transactions もサポートされている。
が、Embedded Data Models を活用することによって、multi-document transactions の使用を必要最低限に抑えた方がよいらしい。

 

スキーマ設計の考え方

問題は Embedded Data Models と Normalized Data Models をどう使い分けるかだが、明確な答えはないようだ。

…と言われても困るので、MongoDB のドキュメントで挙げられている、ざっくりした指針を以下に示す。

Embedded Data Models がよい場合

Normalized Data Models がよい場合

これはあくまで指針であって、当てはまらないケースもあることに注意が必要である。

例えば、一口に「一対多」と言っても「一対少数」なのか「一対数十万」なのかで話は変わってくるわけで、「一対数十万」は Embedded Data Models に向いていない(document がオーバーフローする恐れがあるため)。

※もっと言うと、「一対数十万」の関係でも Embedded Data Models を適応する方法はある。 「一」側に非正規化する方法、「数十万」側に非正規化する方法どちらも実装可能。だから「答えはない」「ケースバイケースです」ということになるのだろう。

 

まとめ