sql >> Databasteknik >  >> NoSQL >> MongoDB

Mest effektiva sättet att lagra kapslade kategorier (eller hierarkiska data) i Mongo?

Det första du vill bestämma är exakt vilken typ av träd du ska använda.

Det stora att tänka på är dina data och åtkomstmönster. Du har redan sagt att 90 % av allt ditt arbete kommer att vara frågar och av ljudet av det (e-handel) kommer uppdateringar endast att köras av administratörer, troligen sällan.

Så du vill ha ett schema som ger dig möjligheten att snabbt söka efter barn genom en väg, t.ex.:Sport -> Basket -> Herrar, Sport -> Tennis -> Damer, och som egentligen inte behöver skala till uppdateringar.

Som du så riktigt påpekade har MongoDB en bra dokumentationssida för detta:https://docs.mongodb.com/manual/applications/data-models-tree-structures/ varvid 10gen faktiskt anger olika modeller och schemametoder för träd och beskriver de huvudsakliga upp- och nedgångarna för dem.

Den som borde fånga ögat om du letar efter att enkelt fråga är materialiserade vägar:https://docs.mongodb.com/manual/tutorial/model-tree-structures-with-materialized-paths/

Detta är en mycket intressant metod att bygga upp träd eftersom för att fråga om exemplet du gav ovan till "Kvinnor" i "Tennis" kan du helt enkelt göra ett förfixat regex (som kan använda indexet:http://docs.mongodb.org/manual/reference/operator/regex/ ) som så:

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

för att hitta alla produkter listade under en viss sökväg i ditt träd.

Tyvärr är den här modellen riktigt dålig på att uppdatera, om du flyttar en kategori eller byter namn måste du uppdatera alla produkter och det kan finnas tusentals produkter under en kategori.

En bättre metod skulle vara att ha ett cat_id på produkten och separera sedan kategorierna i en separat samling med schemat:

{
    _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 involverar dina frågor bara kategoriinsamlingen, vilket borde göra dem mycket mindre och mer presterande. Undantaget från detta är när du tar bort en kategori, produkterna behöver fortfarande beröras.

Så ett exempel på att ändra "Tennis" till "Badmin":

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

Tyvärr tillhandahåller MongoDB ingen dokumentreflektion för tillfället så du måste dra ut dem från klientsidan vilket är lite irriterande, men förhoppningsvis borde det inte leda till att för många kategorier återförs.

Och det är i princip hur det fungerar. Det är lite jobbigt att uppdatera men kraften i att kunna fråga direkt på vilken väg som helst med hjälp av ett index är mer passande för ditt scenario tror jag.

Naturligtvis är den extra fördelen att detta schema är kompatibelt med kapslade uppsättningsmodeller:http://en.wikipedia .org/wiki/Nested_set_model som jag gång på gång har funnit är bara fantastiska för e-handelssajter, till exempel kan tennis ligga under både "Sport" och "Fritid" och du vill ha flera vägar beroende på var användaren kommer ifrån.

Schemat för materialiserade sökvägar stöder detta enkelt genom att bara lägga till en annan path , så enkelt.

Hoppas det är vettigt, ganska lång där.



  1. TypeError:db.collection är inte en funktion, KAN INTE GET

  2. MongoConnectionException - Det gick inte att ansluta till:localhost:27017

  3. Anrop till odefinierad metod MongoDB\Driver\ReadConcern::isDefault()

  4. Mongodb aggregeringsfråga för att subtrahera och gruppera kumulativt värde