Можете или да проектирате схема, където можете да препращате или да вграждате документи. Нека да разгледаме първата опция за вградени документи. С горното приложение можете да съхранявате информацията в документ, както следва:
// 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
документ. Този дизайн има своите предимства, едно от които е локалността на данните. Тъй като MongoDB съхранява данни непрекъснато на диска, поставянето на всички необходими данни в един документ гарантира, че въртящите се дискове ще отнемат по-малко време, за да търсят определено място на диска. Ако вашето приложение често има достъп до table1
информация заедно с table1_lang
данни, тогава почти със сигурност ще искате да отидете по вградения маршрут. Другото предимство на вградените документи е атомарността и изолацията при писане на данни. За да илюстрираме това, кажете, че искате да премахнете документ, който има lang ключ "name" със стойност "foo", това може да се направи с една единствена (атомарна) операция:
db.table.remove({"lang.name": "foo"});
За повече подробности относно моделирането на данни в MongoDB, моля, прочетете документите Въведение в моделирането на данни , по-специално модел Връзки "един към много" с вградени документи
Другата опция за проектиране е препратка към документи, където следвате нормализирана схема. Например:
// 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});
Горната нормализирана схема, използваща подхода за препратка към документ, също има предимство, когато имате релации "един към много" с много непредсказуема арност. Ако имате стотици или хиляди table_lang
документи за дадена table
обект, вграждането има толкова много пречки по отношение на пространствените ограничения, защото колкото по-голям е документът, толкова повече RAM използва, а MongoDB документите имат твърдо ограничение за размер от 16MB.
Общото правило е, че ако моделът на заявка на вашето приложение е добре известен и данните са склонни да бъдат достъпни само по един начин, вграденият подход работи добре. Ако приложението ви прави заявки за данни по много начини или не можете да предвидите моделите на заявките за данни, по-нормализиран модел за препращане на документи ще бъде подходящ за такъв случай.
Справка: