MongoDB でスキーマを定義する
この記事では、MongoDB スキーマとその定義方法について説明します。
MongoDB のスキーマ
データの構造と内容は、JSON オブジェクトであるスキーマによって定義されます。 JSON スキーマ標準を拡張する Realm の BSON スキーマを使用して、アプリのデータ モデルを設計し、ドキュメントが作成、変更、または削除されるたびにドキュメントを検証できます。
正確な値の代わりに、スキーマはさまざまな種類のデータを表します。 多くの組み込みスキーマ タイプが Realm でサポートされています。 テキスト、数値などのプリミティブと、オブジェクトや配列などの構造型を組み合わせて、カスタム オブジェクト型を表すスキーマを形成できます。
たとえば、車に関するデータの基本的なスキーマと、スキーマに準拠するいくつかの車のオブジェクトを以下に示します。
スキーマ:
{
"title": "car",
"required": [
"_id",
"year",
"make",
"model",
"kilometers"
],
"properties": {
"_id": { "bsonType": "objectId" },
"year": { "bsonType": "string" },
"make": { "bsonType": "string" },
"model": { "bsonType": "string" },
"kilometers": { "bsonType": "number" }
}
}
オブジェクト:
{
"_id": ObjectId("5af712eff26b29dc5c51c60f"),
"year": "2022",
"make": "Honda",
"model": "Civic",
"kilometers": 123
}
{
"_id": ObjectId("5af714eff24b294c5251cf04"),
"year": "2016",
"make": "Honda",
"model": "City",
"kilometers": 135794
}
スキーマは、アプリケーションのデータ モデル仕様です。 Realm は、定義したスキーマに準拠するデータを操作するための追加のツールとサービスを提供します。
Realm の多くのアプリケーション サービスはスキーマを使用します。
- Realm と MongoDB Atlas の間でデータを同期するために、Realm Sync はスキーマを使用します。 スキーマに基づいて、慣用的な SDK オブジェクト モデルを開発することもできます。
- GraphQL API は、スキーマを自動的に使用して、タイプ、クエリ、およびミューテーションを自動的に含む GraphQL スキーマを生成します。 スキーマで定義された型を参照するカスタム リゾルバーをアプリの API に追加できます。
- 各リクエストの前後に、データ アクセス ルールにより、データがスキーマに準拠していることを確認します。 さらに、ドキュメントが検証に失敗した場合、レルムはリクエスト全体を防止またはロールバックします。
MongoDB でスキーマを設計する際の考慮事項
- ユーザーの要件に従ってスキーマを設計します。
- オブジェクトを一緒に使用する場合は、それらを 1つのドキュメントに結合します。 必要に応じてそれらを分離します (ただし、結合する必要がないことを確認してください)。
- ディスク容量は計算時間よりも安価であるため、データを複製します (ただし制限があります)。
- 読み込み中ではなく、書き込み中に結合を行います。
- 最も頻繁に使用されるケースに合わせてスキーマを最適化します。
- スキーマで複雑な集計を行います。
これを説明する例を以下に示します。
クライアントがブログまたは Web サイト用のデータベース設計を必要としており、RDBMS と MongoDB のスキーマ設計の違いに気付いたとします。 Web サイトには、次の要件があります。
- すべての投稿には、固有のタイトル、説明、および URL があります。
- すべての投稿に 1つまたは複数のタグを付けることができます。
- すべての投稿には、発行者の名前といいねの総数が表示されます。
- すべての投稿には、ユーザーのコメントとその名前、メッセージ、日時、いいね! が含まれます。
- 各投稿には、コメントがない場合もあれば、複数のコメントがある場合もあります。
RDBMS スキーマでは、上記の要件に対応する設計には、少なくとも 3つのテーブルが含まれます。
MongoDB スキーマでは、デザインには 1つのコレクション ポストと次の構造が含まれます。
{
_id: POST-ID
title: TITLE-OF-POST,
description: POST-DESCRIPTION,
by: POST-BY,
url: URL-OF-POST,
tags: [TAG1, TAG2],
likes: TOTAL-LIKES,
comments: [
{
user: 'COMMENT-BY',
message: TEXT,
dateCreated: DATE-TIME,
like: LIKES
},
{
user: 'COMMENT-BY',
message: TEXT,
dateCreated: DATE-TIME,
like: LIKES
}
]
}
したがって、RDBMS では、3つのテーブルを組み合わせてデータを表示する必要があります。 ただし、MongoDB では、データは 1つのコレクションからのみ表示されます。
MongoDB でスキーマを定義する
型の属性を指定する追加のスキーマは、ルート レベルのコレクション スキーマにあります。 各ルートレベルのスキーマは、次のような object
スキーマです。
{
"bsonType": "object",
"title": "<Type Name>",
"required": ["<Required Field Name>", ...],
"properties": {
"<Field Name>": <Schema>
}
}
ユーザーは、次のサポートされているスキーマ タイプのいずれかを使用して、オブジェクトのプロパティを構成できます。
- オブジェクト
- 配列
- ストリング
- ブール値
- オブジェクト ID
- バイナリデータ
- 混合
- 設定する
- 辞書
MongoDB レルムを使用してスキーマを適用する
MongoDB コレクションに対するすべての書き込み操作 (挿入、更新、および削除) は、MongoDB Realm によってコレクション スキーマに対して検証されます。
また、各リクエストの前後に各ドキュメントを調べて、すべてのプロパティがスキーマと一致しており、無効な変更が行われていないことを確認します。
書き込み操作をクラスターにコミットする前に、Realm はすべてのドキュメント書き込みの結果をチェックし、それらをスキーマと比較します。
MongoDB Realm は、リクエストに変更を加えることなく、リクエストの書き込み操作の結果がスキーマに適合しない場合、ユーザーにエラーを配信します。
この例を以下に示します。 コレクションには次のスキーマがあります。
{
"title": "person",
"properties": {
"_id": {"bsonType": "objectId" },
"name": {"bsonType": "string" }
}
}
すべてのフィールドへの完全なアクセス権を持つユーザーが、特定のドキュメントの name
フィールドを変更したいと考えています。 彼らは次のことについて尋ねます。
collection.updateOne(
{ "_id": BSON.ObjectId("5ae782e48f25b9dc5c51c4d0") },
{ "$set": { "name": 22 } }
)
クエリは、name
の値を数値 22
に設定しようとします。 それにもかかわらず、スキーマは値が文字列であることを指定します。
ユーザーがドキュメントを更新する権限を受け取ったとしても、書き込み結果がスキーマに準拠していないため、MongoDB Realm はこの書き込み操作を拒否します。