sql >> Databáze >  >> NoSQL >> MongoDB

Populace mangusty vs vnoření objektů

První věc, kterou je třeba pochopit o populaci mangust, je to, že to není magie, ale pouze pohodlná metoda, která vám umožní získat související informace, aniž byste to všechno dělali sami.

Tento koncept je v podstatě pro použití tam, kde se rozhodnete, že budete muset umístit data do samostatné kolekce, spíše než tato data vložit, a vaše hlavní úvahy by měly být typicky na velikosti dokumentu nebo tam, kde související informace podléhají častým aktualizacím, které by údržba vložených dat je nepraktická.

Část „nekouzelná“ spočívá v tom, že v podstatě to, co se děje pod krytem, ​​je to, že když „odkážete“ na jiný zdroj, funkce naplnění vytvoří další dotaz/dotazy na tuto „související“ kolekci, aby „sloučila“ výsledky nadřazené položky. objekt, který jste získali. Mohli byste to udělat sami, ale metoda je zde pro pohodlí, která zjednodušuje úkol. Zjevnou úvahou o „výkonu“ je, že neexistuje jediný okružní výlet do databáze (instance MongoDB), aby bylo možné získat všechny informace. Vždy je více než jeden.

Jako vzorek vezměte dvě kolekce:

{ 
    "_id": ObjectId("5392fea00ff066b7d533a765"),
    "customerName": "Bill",
    "items": [
        ObjectId("5392fee10ff066b7d533a766"),
        ObjectId("5392fefe0ff066b7d533a767")
    ]
}

A položky:

{ "_id": ObjectId("5392fee10ff066b7d533a766"), "prod": "ABC", "qty": 1 }
{ "_id": ObjectId("5392fefe0ff066b7d533a767"), "prod": "XYZ", "qty": 2 }

To „nejlepší“, co lze udělat pomocí „referenčního“ modelu nebo použití obsadit (pod kapotou), je toto:

var order = db.orders.findOne({ "_id": ObjectId("5392fea00ff066b7d533a765") });
order.items = db.items.find({ "_id": { "$in": order.items } ).toArray();

Takže jasně existují „alespoň“ dva dotazy a operace, aby se tato data „spojila“.

Koncept vkládání je v podstatě odpovědí MongoDB na to, jak se vypořádat s nepodporováním „připojení“. Takže namísto rozdělení dat do normalizovaných kolekcí se pokusíte „související“ data vložit přímo do dokumentu, který je používá. Výhodou zde je, že existuje jediná operace „čtení“ pro načtení „souvisejících“ informací a také jeden bod operací „zápisu“ pro aktualizaci „nadřazených“ a „podřízených“ položek, i když často není možné do nich zapisovat. "mnoho" potomků najednou bez zpracování "seznamů" na klientovi nebo jiného přijímání "vícenásobných" operací zápisu a nejlépe v "dávkovém" zpracování.

Data pak vypadají spíše takto (ve srovnání s příkladem výše):

{ 
    "_id": ObjectId("5392fea00ff066b7d533a765"),
    "customerName": "Bill",
    "items": [
        { "_id": ObjectId("5392fee10ff066b7d533a766"), "prod": "ABC", "qty": 1 },
        { "_id": ObjectId("5392fefe0ff066b7d533a767"), "prod": "XYZ", "qty": 2 }
    ]
}

Ve skutečnosti je tedy načtení dat jen otázkou:

db.orders.findOne({ "_id": ObjectId("5392fea00ff066b7d533a765") });

Výhody a nevýhody obou budou vždy do značné míry záviset na vzoru použití vaší aplikace. Ale na první pohled:

Vkládání

  • Celková velikost dokumentu s vloženými daty obvykle nepřesáhne 16 MB úložiště (limit BSON) nebo jinak (jako vodítko) mají pole obsahující 500 nebo více položek.

  • Data, která jsou vložena, obecně nevyžadují časté změny. Takže byste mohli žít s „duplikací“, která pochází z denormalizace, která nevede k nutnosti aktualizovat tyto „duplikáty“ stejnými informacemi v mnoha nadřazených dokumentech, jen abyste vyvolali změnu.

  • Související údaje se často používají ve spojení s rodiči. Což znamená, že pokud vaše případy „čtení/zápis“ v podstatě vždy potřebují „číst/zapisovat“ jak nadřazenému, tak podřízenému, pak má smysl vkládat data pro atomické operace.

Odkazování

  • Související data vždy překročí limit 16 MB BSON. Vždy můžete uvažovat o hybridním přístupu „bucketování“, ale obecný tvrdý limit hlavního dokumentu nelze prolomit. Běžné případy jsou „příspěvky“ a „komentáře“, kdy se očekává, že aktivita „komentářů“ bude velmi velká.

  • Související údaje vyžadují pravidelnou aktualizaci. Nebo v podstatě případ, kdy „normalizujete“, protože tato data jsou „sdílena“ mezi mnoha rodiči a „související“ data se mění natolik často, že by bylo nepraktické aktualizovat vložené položky v každé „rodičovské“ položce, kde se tato „dětská“ položka vyskytuje. . Jednodušší případ je pouze odkazovat na „dítě“ a provést změnu jednou.

  • Je zde jasné oddělení čtení a zápisu. V případě, kdy možná nebudete vždy vyžadovat tyto „související“ informace při čtení „rodiče“ nebo jinak nebudete muset vždy „rodiče“ při psaní s dítětem měnit, může existovat dobrý důvod k oddělení modelu. jak je uvedeno. Kromě toho, pokud existuje obecná potřeba aktualizovat mnoho „poddokumentů“ najednou, v nichž jsou tyto „poddokumenty“ ve skutečnosti odkazy na jinou kolekci, pak je implementace často efektivnější, když jsou data v samostatném souboru. kolekce.

Takže ve skutečnosti existuje mnohem širší diskuse o „výhodách/záporech“ obou pozic v dokumentaci MongoDB o datovém modelování, která pokrývá různé případy použití a způsoby přístupu buď pomocí vkládání nebo referenčního modelu, jak je podporováno metodou naplnění.

Doufejme, že „tečky“ jsou užitečné, ale obecně se doporučuje zvážit vzorce využití dat vaší aplikací a vybrat si, co je nejlepší. Možnost vložit "by měla" být důvodem, proč jste si vybrali MongoDB, ale ve skutečnosti to bude to, jak vaše aplikace "používá data", což rozhoduje o tom, která metoda vyhovuje které části vašeho datového modelování (protože není "vše nebo nic") nejlepší.

  1. Všimněte si, že protože toto bylo původně napsáno, MongoDB zavedlo $lookup operátor, který skutečně provádí „spojení“ mezi kolekcemi na serveru. Pro účely obecné diskuse zde, whist "lepší" ve většině případů než režie "vícenásobného dotazu" způsobená populate() a obecně „více dotazů“, stále existuje „značná režie“ vzniklé s jakýmkoli $lookup operace.

Základním principem návrhu je „vložený“ znamená „již tam“ na rozdíl od „načítání odjinud“. V podstatě rozdíl mezi „v kapse“ a „na polici“ a z hlediska I/O obvykle spíše jako „na polici v knihovně v centru“ a zejména dále pro síťové požadavky.




  1. Najděte dokumenty s poli, která neobsahují dokument s konkrétní hodnotou pole v MongoDB

  2. MongoDB sort()

  3. MongoDB $toLower

  4. Jak zrychlit MongoDB Inserts/s?