To je dobrá otázka, která ilustruje problémy s overemebeddingem a jak se s ním vypořádat.
Příklad:Přidání lajků
Zůstaňme u příkladu uživatelů, kterým se líbí příspěvky, což je jednoduchý příklad. Podle toho by se muselo nakládat s ostatními vztahy.
Máte naprostou pravdu, že ukládání lajků uvnitř příspěvku by dříve nebo později vedlo k problému, že velmi oblíbené příspěvky by dosáhly limitu velikosti.
Takže jste se správně vrátili k vytvoření post_likes
sbírka. Proč tomu říkám správně? Protože vyhovuje vašim případům použití a funkčním a nefunkčním požadavkům!
- Škáluje se neomezeně (dobře, existuje teoretický limit, ale je obrovský)
- Snadná údržba (vytvořte jedinečný index přes
post_id
aliked_user_id
) a použití (uživatel i příspěvek jsou známé, takže přidání lajku je jednoduché vložení nebo spíše upsert) - Snadno můžete zjistit, kterým uživatelům se líbí který příspěvek a který příspěvek se líbí kterým uživatelům
Sbírku bych však trochu rozšířil, abych zabránil zbytečným dotazům pro určité případy použití, které jsou časté.
Předpokládejme prozatím, že názvy příspěvků a uživatelská jména nelze změnit. V takovém případě by následující datový model mohl dávat větší smysl
{
_id: new ObjectId(),
"post_id": someValue,
"post_title": "Cool thing",
"liked_user_id": someUserId,
"user_name": "JoeCool"
}
Nyní předpokládejme, že chcete zobrazit uživatelská jména všech uživatelů, kterým se příspěvek líbí. S výše uvedeným modelem by to byl jeden, poměrně rychlý dotaz:
db.post_likes.find(
{"postId":someValue},
{_id:0,user_name:1}
)
S uloženými pouze ID by tento poměrně obvyklý úkol vyžadoval alespoň dva dotazy a – vzhledem k omezení, že příspěvek může mít nekonečný počet lajků – potenciálně obrovský spotřeba paměti (uživatelská ID budete muset uložit do paměti RAM).
Je pravda, že to vede k určité nadbytečnosti, ale i když miliony lidí lajkují příspěvek, mluvíme pouze o několika megabajtech relativně levného (a snadno škálovatelného) místa na disku při získání velkého výkonu z hlediska uživatelské zkušenosti.
Nyní přichází věc:I když se uživatelská jména a názvy příspěvků mohou změnit, stačilo provést vícenásobnou aktualizaci:
db.post_likes.update(
{"post_id":someId},
{ $set:{ "post_title":newTitle} },
{ multi: true}
)
Obchodujete s tím, že provedení některých poměrně vzácných věcí, jako je změna uživatelského jména nebo příspěvku pro extrémní rychlost pro případy použití, které se stávají extrémně často, chvíli trvá.
Sečteno a podtrženo
Mějte na paměti, že MongoDB je databáze orientovaná na dokumenty. Proto zdokumentujte události, které vás zajímají, s hodnotami, které potřebujete pro budoucí dotazy, a podle toho modelujte svá data.