ドキュメントを参照または埋め込むことができるスキーマを設計できます。埋め込みドキュメントの最初のオプションを見てみましょう。上記のアプリケーションを使用すると、次のように情報をドキュメントに保存できます。
// db.table1 schema
{
"_id": 3, // table1_id
"is_active": true,
"created": ISODate("2015-04-07T16:00:30.798Z"),
"lang": [
{
"name": "foo",
"surname": "bar",
"address": "xxx"
},
{
"name": "abc",
"surname": "def",
"address": "xyz"
}
]
}
上記のスキーマ例では、基本的にtable1_lang
を埋め込んでいます。 メインのtable1
内の情報 資料。この設計にはメリットがあり、その1つがデータの局所性です。 MongoDBはデータをディスクに連続して保存するため、必要なすべてのデータを1つのドキュメントに入れることで、回転するディスクがディスク上の特定の場所を探すのにかかる時間が短縮されます。アプリケーションが頻繁にtable1
にアクセスする場合 table1_lang
と一緒に情報 データの場合、ほぼ確実に埋め込みルートに移動する必要があります。埋め込みドキュメントのもう1つの利点は、データの書き込みにおける原子性と分離です。これを説明するために、値が「foo」のlangキー「name」を持つドキュメントを削除したい場合、これは1つの(アトミック)操作で実行できます。
db.table.remove({"lang.name": "foo"});
MongoDBでのデータモデリングの詳細については、ドキュメントをお読みください データモデリングの概要 、具体的には Model埋め込みドキュメントとの1対多の関係
もう1つの設計オプションは、正規化されたスキーマに従うドキュメントを参照することです。例:
// db.table1 schema
{
"_id": 3
"is_active": true
"created": ISODate("2015-04-07T16:00:30.798Z")
}
// db.table1_lang schema
/*
1
*/
{
"_id": 1,
"table1_id": 3,
"name": "foo",
"surname": "bar",
"address": "xxx"
}
/*
2
*/
{
"_id": 2,
"table1_id": 3,
"name": "abc",
"surname": "def",
"address": "xyz"
}
上記のアプローチにより、クエリの実行の柔軟性が向上します。たとえば、すべての子table1_lang
を取得するには メインの親エンティティtable1
のドキュメント ID 3を使用すると簡単になり、コレクションtable1_lang
に対してクエリを作成するだけです。 :
db.table1_lang.find({"table1_id": 3});
ドキュメント参照アプローチを使用した上記の正規化されたスキーマには、非常に予測不可能なアリティを持つ1対多の関係がある場合にも利点があります。数百または数千のtable_lang
がある場合 与えられたtable
ごとのドキュメント エンティティ、埋め込みには、空間的な制約に関する限り、非常に多くの欠点があります。ドキュメントが大きいほど、使用するRAMが多くなり、MongoDBドキュメントのハードサイズ制限は16MBです。
一般的な経験則では、アプリケーションのクエリパターンがよく知られており、データへのアクセス方法が1つだけである場合は、埋め込みアプローチが適切に機能します。アプリケーションがさまざまな方法でデータをクエリする場合、またはデータクエリのパターンを予測できない場合は、より正規化されたドキュメント参照モデルがそのような場合に適しています。
参照:
MongoDBが適用した設計パターン:RickCopelandによる主要なNoSQLデータベースの実用的なユースケース