MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Najbardziej efektywny sposób przechowywania zagnieżdżonych kategorii (lub danych hierarchicznych) w Mongo?

Pierwszą rzeczą, którą chcesz zdecydować, jest dokładnie jakiego rodzaju drzewa użyjesz.

Ważną rzeczą do rozważenia są dane i wzorce dostępu. Wspomniałeś już, że 90% całej Twojej pracy będzie dotyczyć zapytań i, jak się wydaje, aktualizacje (e-commerce) będą uruchamiane tylko przez administratorów, najprawdopodobniej rzadko.

Potrzebujesz więc schematu, który da ci możliwość szybkiego zadawania pytań o dziecko poprzez ścieżkę, np.:Sport -> Koszykówka -> Mężczyźni, Sport -> Tenis -> Kobiety i nie musi naprawdę skalować się do aktualizacji.

Jak słusznie zauważyłeś, MongoDB ma dobrą stronę z dokumentacją:https://docs.mongodb.com/manual/applications/data-models-tree-structures/ przy czym 10gen faktycznie określa różne modele i metody schematów dla drzew oraz opisuje ich główne wzloty i upadki.

Ten, który powinien przyciągnąć wzrok, jeśli chcesz łatwo zadawać zapytania, to zmaterializowane ścieżki:https://docs.mongodb.com/manual/tutorial/model-tree-structures-with-materialized-paths/

Jest to bardzo ciekawa metoda budowania drzew, ponieważ do zapytania na podanym powyżej przykładzie do "Kobiety" w "Tenisie" można po prostu zrobić wstępnie ustalone wyrażenie regularne (które może użyć indeksu:http://docs.mongodb.org/manual/reference/operator/regex/ ) tak:

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

aby znaleźć wszystkie produkty wymienione pod określoną ścieżką twojego drzewa.

Niestety ten model jest naprawdę kiepski w aktualizacji, jeśli przeniesiesz kategorię lub zmienisz jej nazwę, musisz zaktualizować wszystkie produkty, a w jednej kategorii mogą znajdować się tysiące produktów.

Lepszą metodą byłoby umieszczenie cat_id na produkcie, a następnie podziel kategorie w osobną kolekcję ze schematem:

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

Więc teraz Twoje zapytania dotyczą tylko kolekcji kategorii, co powinno sprawić, że będą one znacznie mniejsze i bardziej wydajne. Wyjątkiem jest sytuacja, gdy usuniesz kategorię, produkty nadal będą wymagały dotknięcia.

Przykład zmiany „Tenis” na „Badmin”:

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

Niestety MongoDB nie zapewnia obecnie odzwierciedlenia dokumentów w zapytaniu, więc musisz wyciągnąć je po stronie klienta, co jest trochę denerwujące, jednak miejmy nadzieję, że nie powinno to spowodować przywrócenia zbyt wielu kategorii.

I tak to działa naprawdę. Aktualizacja jest trochę kłopotliwa, ale uważam, że możliwość natychmiastowego zapytania na dowolnej ścieżce za pomocą indeksu jest bardziej odpowiednia dla twojego scenariusza.

Oczywiście dodatkową korzyścią jest to, że ten schemat jest zgodny z zagnieżdżonymi modelami zestawów:http://en.wikipedia .org/wiki/Nested_set_model które od czasu do czasu uważam, że są po prostu niesamowite dla witryn e-commerce, na przykład tenis może znajdować się zarówno pod hasłem „Sport”, jak i „Czas wolny”, a potrzebujesz wielu ścieżek w zależności od tego, skąd pochodzi użytkownik.

Schemat zmaterializowanych ścieżek łatwo to obsługuje, po prostu dodając kolejną path , to proste.

Mam nadzieję, że to ma sens, dość długi.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Filtruj według kraju i swobodnego wyszukiwania tekstu mongodb za pomocą mongoose

  2. mongodb:aktualizowanie elementów?

  3. Jak utworzyć indeks tekstowy w mongodb z golangiem i biblioteką mgo?

  4. Jak powiedzieć... dopasuj, gdy pole jest liczbą... w mongodb?

  5. Uzyskaj dokument w MongoDB bez określania kolekcji