sql >> Database >  >> NoSQL >> MongoDB

Meest efficiënte manier om geneste categorieën (of hiërarchische gegevens) in Mongo op te slaan?

Het eerste dat u wilt beslissen, is wat voor soort boom u precies gaat gebruiken.

Het belangrijkste om te overwegen zijn uw gegevens en toegangspatronen. Je hebt al aangegeven dat 90% van al je werk query's zal zijn en dat (e-commerce) updates alleen door beheerders zullen worden uitgevoerd, hoogstwaarschijnlijk zelden.

Dus je wilt een schema dat je de kracht geeft om snel te zoeken naar kinderen via een pad, d.w.z.:Sport -> Basketbal -> Heren, Sport -> Tennis -> Dames, en dat niet echt hoeft te worden geschaald naar updates.

Zoals je terecht opmerkte heeft MongoDB hier een goede documentatiepagina voor:https://docs.mongodb.com/manual/applications/data-models-tree-structures/ waarbij 10gen in feite verschillende modellen en schemamethoden voor bomen beschrijft en de belangrijkste ups en downs ervan beschrijft.

Degene die in het oog moet springen als u gemakkelijk query's wilt uitvoeren, zijn gematerialiseerde paden:https://docs.mongodb.com/manual/tutorial/model-tree-structures-with-materialized-paths/

Dit is een zeer interessante methode om bomen op te bouwen, want om een ​​query uit te voeren op het voorbeeld dat u hierboven gaf in "Womens" in "Tennis", zou u eenvoudig een vooraf vastgestelde regex kunnen doen (die de index kan gebruiken:http://docs.mongodb.org/manual/reference/operator/regex/ ) vind ik leuk:

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

om alle producten te vinden die onder een bepaald pad van uw boom staan ​​vermeld.

Helaas is dit model erg slecht in het updaten. Als je een categorie verplaatst of de naam ervan verandert, moet je alle producten bijwerken en kunnen er duizenden producten onder één categorie zijn.

Een betere methode zou zijn om een ​​cat_id . te huisvesten op het product en scheid de categorieën vervolgens in een aparte verzameling met het schema:

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

Dus nu hebben uw zoekopdrachten alleen betrekking op de categorieënverzameling, waardoor ze veel kleiner en beter presteren. De uitzondering hierop is dat wanneer u een categorie verwijdert, de producten nog steeds moeten worden aangeraakt.

Dus een voorbeeld van het veranderen van "Tennis" in "Badmin":

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

Helaas biedt MongoDB op dit moment geen reflectie op het document, dus je moet ze wel uit de client halen, wat een beetje vervelend is, maar hopelijk leidt dit er niet toe dat er te veel categorieën worden teruggebracht.

En dit is eigenlijk hoe het echt werkt. Het is een beetje vervelend om te updaten, maar de kracht van het direct kunnen zoeken op elk pad met behulp van een index past beter bij uw scenario, denk ik.

Het extra voordeel is natuurlijk dat dit schema compatibel is met geneste setmodellen:http://en.wikipedia .org/wiki/Nested_set_model waarvan ik keer op keer heb ontdekt dat ze gewoon geweldig zijn voor e-commercesites. Tennis kan bijvoorbeeld onder zowel 'Sport' als 'Vrije tijd' staan ​​en je wilt meerdere paden, afhankelijk van waar de gebruiker vandaan komt.

Het schema voor gematerialiseerde paden ondersteunt dit eenvoudig door gewoon een ander path toe te voegen , zo simpel.

Ik hoop dat het logisch is, nogal een lange daar.



  1. MongoDB-aggregaties met Java

  2. Tips voor het upgraden naar de nieuwste MongoDB-versie

  3. Mongodb, linq-chauffeur. Hoe te construeren Bevat met variabele of instructies

  4. Vergelijk ingesloten document met bovenliggend veld met mongoDB