sql >> Database teknologi >  >> NoSQL >> MongoDB

Mest effektive måde at gemme indlejrede kategorier (eller hierarkiske data) i Mongo?

Det første du vil beslutte dig for er præcis, hvilken slags træ du vil bruge.

Den store ting at overveje er dine data og adgangsmønstre. Du har allerede udtalt, at 90 % af alt dit arbejde vil være forespørgsler, og ved lyden af ​​det (e-handel) vil opdateringer kun blive kørt af administratorer, højst sandsynligt sjældent.

Så du vil have et skema, der giver dig mulighed for hurtigt at forespørge på barnet gennem en sti, f.eks.:Sport -> Basketball -> Mænd, Sport -> Tennis -> Kvinder, og ikke virkelig behøver at skalere til opdateringer.

Som du så rigtigt påpegede, har MongoDB en god dokumentationsside for dette:https://docs.mongodb.com/manual/applications/data-models-tree-structures/ hvorved 10gen faktisk angiver forskellige modeller og skemametoder for træer og beskriver de vigtigste op- og nedture i dem.

Den, der bør fange øjet, hvis du ønsker at forespørge let, er materialiserede stier:https://docs.mongodb.com/manual/tutorial/model-tree-structures-with-materialized-paths/

Dette er en meget interessant metode til at opbygge træer, da for at forespørge på eksemplet, du gav ovenfor, til "Kvinder" i "Tennis", kunne du simpelthen lave et forudbestemt regex (som kan bruge indekset:http://docs.mongodb.org/manual/reference/operator/regex/ ) sådan:

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

for at finde alle produkter, der er angivet under en bestemt sti i dit træ.

Desværre er denne model virkelig dårlig til at opdatere, hvis du flytter en kategori eller ændrer dens navn, skal du opdatere alle produkter, og der kan være tusindvis af produkter under én kategori.

En bedre metode ville være at huse et cat_id på produktet og adskil derefter kategorierne i en separat samling med skemaet:

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

Så nu involverer dine forespørgsler kun kategorisamlingen, hvilket burde gøre dem meget mindre og mere effektive. Undtagelsen fra dette er, når du sletter en kategori, produkterne skal stadig røres.

Så et eksempel på at ændre "Tennis" til "Badmin":

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

Desværre leverer MongoDB ingen dokumentrefleksion i øjeblikket, så du er nødt til at trække dem ud af klientsiden, hvilket er lidt irriterende, men forhåbentlig skulle det ikke resultere i, at for mange kategorier bringes tilbage.

Og sådan fungerer det i bund og grund. Det er lidt besværligt at opdatere, men styrken ved at være i stand til at forespørge med det samme på enhver sti ved hjælp af et indeks er mere passende til dit scenarie, tror jeg.

Den ekstra fordel er naturligvis, at dette skema er kompatibelt med indlejrede sætmodeller:http://en.wikipedia .org/wiki/Nested_set_model som jeg gang på gang har fundet ud af, er bare fantastiske til e-handelssider, for eksempel kan Tennis være under både "Sport" og "Fritid", og du vil have flere veje afhængigt af, hvor brugeren kom fra.

Skemaet for materialiserede stier understøtter nemt dette ved blot at tilføje en anden path , så enkelt.

Håber det giver mening, ret lang en der.



  1. Håndtering af MySQL, MongoDB og PostgreSQL med ChatOps fra Slack

  2. Brug af Mongo / BSON ObjectId med Parse Server

  3. Håndtering af forbindelser

  4. MongoDb søger indlejret array mellem dateTimes ved hjælp af Robomongo