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

Nejúčinnější způsob, jak ukládat vnořené kategorie (nebo hierarchická data) v Mongo?

První věc, kterou se chcete rozhodnout, je přesně to, jaký druh stromu použijete.

Velkou věcí, kterou je třeba zvážit, jsou vaše data a vzorce přístupu. Již jste uvedli, že 90 % veškeré vaší práce bude dotazování a podle toho (e-commerce) aktualizace budou spouštět pouze administrátoři, s největší pravděpodobností zřídka.

Takže chcete schéma, které vám umožní rychle se dotazovat na dítě prostřednictvím cesty, tj.:Sport -> Basketbal -> Pánské, Sportovní -> Tenis -> Dámské, a ve skutečnosti nepotřebujete skutečně aktualizovat.

Jak jste správně zdůraznil, MongoDB má k tomu dobrou dokumentační stránku:https://docs.mongodb.com/manual/applications/data-models-tree-structures/ přičemž 10gen ve skutečnosti uvádí různé modely a metody schémat pro stromy a popisuje jejich hlavní vzestupy a pády.

Ta, která by měla upoutat pozornost, pokud hledáte snadné dotazování, jsou materializované cesty:https://docs.mongodb.com/manual/tutorial/model-tree-structures-with-materialized-paths/

Toto je velmi zajímavá metoda pro vytváření stromů, protože k dotazu na příklad, který jste uvedli výše, na „Ženy“ v „Tenisu“, můžete jednoduše vytvořit předem stanovený regulární výraz (který může používat index:http://docs.mongodb.org/manual/reference/operator/regex/ ) takhle:

db.products.find({category: /^Sports,Tennis,Womens[,]/})

najít všechny produkty uvedené pod určitou cestou vašeho stromu.

Bohužel tento model je opravdu špatný v aktualizaci, pokud přesunete kategorii nebo změníte její název, musíte aktualizovat všechny produkty a v jedné kategorii mohou být tisíce produktů.

Lepší metodou by bylo umístit cat_id na produktu a poté oddělte kategorie do samostatné kolekce se schématem:

{
    _id: ObjectId(),
    name: 'Women\'s',
    path: 'Sports,Tennis,Womens',
    normed_name: 'all_special_chars_and_spaces_and_case_senstive_letters_taken_out_like_this'
}

Nyní tedy vaše dotazy zahrnují pouze kolekci kategorií, díky čemuž by měly být mnohem menší a výkonnější. Výjimkou je, že když smažete kategorii, produkty se budou muset stále dotknout.

Takže příklad změny „Tenis“ na „Badmin“:

db.categories.update({path:/^Sports,Tennis[,]/}).forEach(function(doc){
    doc.path = doc.path.replace(/,Tennis/, ",Badmin");
    db.categories.save(doc);
});

Bohužel MongoDB v tuto chvíli neposkytuje žádnou reflexi dokumentů v dotazu, takže je musíte vytáhnout na straně klienta, což je trochu nepříjemné, ale doufejme, že by to nemělo vést k tomu, že by se vrátilo příliš mnoho kategorií.

A takhle to v podstatě opravdu funguje. Aktualizace je trochu bolestivá, ale myslím, že schopnost okamžitého dotazování na jakékoli cestě pomocí indexu je pro váš scénář vhodnější.

Samozřejmě další výhodou je, že toto schéma je kompatibilní s modely vnořených sad:http://en.wikipedia .org/wiki/Nested_set_model o kterých jsem znovu a znovu zjistil, že jsou prostě úžasné pro weby elektronického obchodu, například tenis může být pod položkou „Sport“ i „Volný čas“ a chcete více cest v závislosti na tom, odkud uživatel přišel.

Schéma pro materializované cesty to snadno podporuje přidáním další path , tak jednoduché.

Doufám, že to dává smysl, je to docela dlouhé.



  1. MongoDB $ měsíc

  2. jak připojit mongoDB k serveru?

  3. Proč se KEYS nedoporučuje používat v Redis?

  4. Vyberte Odpovídající prvek pole a Vraťte vybraná pole