Du måste överväga vilken typ av frågor du kommer att behöva utföra och hur ofta varje typ kommer att behövas. När jag arbetade med något liknande kom jag på sex möjliga åtgärder:
- Gör något med föräldern
- Gör något med barnen
- Gör något med förfäderna (föräldrar till föräldrar, föräldrar till föräldrar till föräldrar, etc.)
- Gör något med ättlingarna (barn till barn, barn till barn till barn, etc.)
- Ändra relationer (lägg till/flytta/ta bort noder i hierarkin)
- Ändra huvuddata i den aktuella noden (t.ex. ändra värdet i fältet "titel")
Du vill uppskatta hur viktig var och en av dessa är för din ansökan.
Om det mesta av ditt arbete innebär att arbeta med lagrad data för en viss artikel, inklusive dess närmaste förälder och barn, första idén är mest användbar. I MongoDB är det faktiskt ganska vanligt att placera all information du behöver i samma dokument snarare än att referera till den externt så att du bara behöver hämta en sak och bara arbeta med den datan. De fyra sista åtgärderna i listan är dock mer knepiga.
I synnerhet kommer du att behöva gå genom trädet för att hämta förfäder och ättlingar i det här fallet, gå igenom mellanliggande dokument och följa en väg, även om du kanske bara bryr dig om det sista dokumentet i vägen. Detta kan vara långsamt för långa hierarkier. Att ändra relationer kan kräva att mycket information flyttas runt i flera dokument på grund av all data som finns i vart och ett. Men även att ändra ett enstaka fält som "titel" kan vara irriterande, eftersom du måste tänka på det faktum att detta fält finns i flera olika dokument, antingen som ett huvudfält eller under förälder- eller barnfälten.
I grund och botten är din första idé fungerar bäst i fler statiska applikationer där du inte kommer att ändra data mycket efter att du först skapat den, men där du behöver läsa den regelbundet.
MongoDB-dokumentationen har fem rekommenderade tillvägagångssätt för hantering av trädliknande (hierarkiska) strukturer. Alla har olika fördelar och nackdelar, även om de alla gör det enkelt att uppdatera huvuddata i en artikel genom att bara behöva göra det i ett dokument.
- Föräldrareferenser :varje nod innehåller en referens till sin förälder.
- Fördelar :
- Snabb föräldrasökning (sök med "_id" =din dokumenttitel, returnera "förälder"-fält)
- Snabb uppslagning av barn (uppslagning av "förälder" =din dokumenttitel, som returnerar alla underordnade dokument)
- Att uppdatera relationer är bara en fråga om att ändra fältet "förälder"
- Ändring av underliggande data kräver ändringar av endast ett dokument
- Nackdelar :
- Sökning efter förfäder och ättlingar går långsamt och kräver en genomgång
- Barnreferenser :varje nod innehåller en referensmatris till sina underordnade
- Fördelar :
- Snabb hämtning av barn (lämna tillbaka barnmatrisen)
- Snabb uppdatering av relationer (uppdatera bara barnens array där det behövs)
- Nackdelar :
- För att hitta en förälder måste du leta upp ditt _id i alla underordnade arrayer i alla dokument tills du hittar det (eftersom föräldern kommer att innehålla den aktuella noden som ett barn)
- Sökning av förfäder och avkomlingar kräver genomgångar av trädet
- Fördelar :
- Array av förfäder :varje nod innehåller en referens till en array av dess förfäder och dess förälder
- Fördelar :
- Snabb hämtning av förfäder (ingen genomgång krävs för att hitta en specifik)
- Lätt att söka efter förälder och barn enligt metoden "Föräldrareferenser"
- För att hitta ättlingar, slå bara upp förfäderna, eftersom alla ättlingar måste innehålla samma förfäder
- Nackdelar :
- Behöver oroa dig för att hålla uppsättningen av förfäder samt det överordnade fältet uppdaterade när det sker en förändring i relationer, ofta över flera dokument.
- Fördelar :
- Materialiserade sökvägar :varje nod innehåller en sökväg till sig själv - kräver regex
- Fördelar :
- Lätt att hitta barn och ättlingar med hjälp av regex
- Kan använda en sökväg för att hämta förälder och förfäder
- Flexibilitet, till exempel att hitta noder med partiella sökvägar
- Nackdelar :
- Förändringar av relationer är svåra eftersom de kan kräva ändringar av sökvägar över flera dokument
- Fördelar :
- Inkapslade uppsättningar :Varje nod innehåller ett "vänster" och "höger" fält för att hjälpa till att hitta underträd
- Fördelar :
- Lätt att hämta ättlingar på ett optimalt sätt genom att söka mellan "vänster" och "höger"
- Precis som "Parent Reference"-metoden är det lätt att hitta förälder och barn
- Nackdelar :
- Behöver gå igenom struktur för att hitta förfäder
- Relationsändringar fungerar sämst här än något annat alternativ eftersom varje enskilt dokument i trädet kan behöva ändras för att säkerställa att "vänster" och "höger" fortfarande är meningsfulla när något ändras i hierarkin
- Fördelar :
De fem tillvägagångssätten diskuteras mer i detalj i MongoDB-dokumentationen .
Din andra idé kombinerar tillvägagångssätten "förälderreferenser" och "barnreferenser" som diskuterats ovan. Detta tillvägagångssätt gör det enkelt att hitta både barnen och föräldern och gör det enkelt att uppdatera relationer och huvuddata för en artikel (även om du behöver uppdatera både förälder- och barnfälten), men du måste fortfarande gå igenom det att hitta förfäder och ättlingar.
Om du är intresserad av att hitta förfäder och ättlingar (och bryr dig om detta mer än att enkelt kunna uppdatera relationer), kan du överväga att lägga till en förfäder-array till din andra idé för att göra det också enkelt att fråga efter förfäder och ättlingar. Naturligtvis blir det jobbigt att uppdatera relationer om du gör det här.
Slutsats:
-
I slutändan beror allt på vilka åtgärder som behövs mest. Eftersom du arbetar med artiklar, vars underliggande data (som titeln) kan ändras ofta, kanske du vill undvika den första idén eftersom du behöver uppdatera inte bara huvuddokumentet för den artikeln utan alla underordnade dokument samt förälder.
-
Din andra idé gör det enkelt att hämta den närmaste föräldern och barnen. Att uppdatera relationer är inte heller alltför svårt (det är verkligen bättre än några av de andra tillgängliga alternativen).
-
Om du verkligen vill göra det enkelt att hitta förfäder och ättlingar på bekostnad av att uppdatera relationer lika enkelt, välj att inkludera en mängd förfäderreferenser.
-
Försök i allmänhet att minimera antalet genomgångar som krävs, eftersom de kräver att du kör någon form av iteration eller rekursion för att komma till den data du vill ha. Om du värdesätter möjligheten att uppdatera relationer bör du också välja ett alternativ som ändrar färre noder i trädet (förälderreferenser, barnreferenser och din andra idé kan göra detta).