Det här är en bra fråga som illustrerar problemen med överebedding och hur man hanterar det.
Exempel:Gilla inlägg
Låt oss hålla oss till exemplet med användare som gillar inlägg, vilket är ett enkelt exempel. De andra relationerna skulle behöva hanteras i enlighet med detta.
Du har helt rätt i att med att lagra gilla-markeringar i inlägget skulle det förr eller senare leda till problemet att mycket populära inlägg skulle nå storleksgränsen.
Så du föll korrekt tillbaka för att skapa en post_likes
samling. Varför kallar jag detta korrekt? Eftersom det passar dina användningsfall och funktionella och icke-funktionella krav!
- Den skalar oändligt (det finns en teoretisk gräns, men den är enorm)
- Det är lätt att underhålla (skapa ett unikt index över
post_id
ochliked_user_id
) och använd (både användaren och inlägget är kända, så att lägga till en like är en enkel infogning eller mer troligt en upsert) - Du kan enkelt ta reda på vilka användare som gillar vilket inlägg och vilket inlägg som gillas av vilka användare
Jag skulle dock utöka samlingen lite för att förhindra onödiga frågor för vissa användningsfall som är frekventa.
Låt oss för närvarande anta att inläggets titlar och användarnamn inte kan ändras. I så fall kan följande datamodell vara mer vettig
{
_id: new ObjectId(),
"post_id": someValue,
"post_title": "Cool thing",
"liked_user_id": someUserId,
"user_name": "JoeCool"
}
Låt oss nu anta att du vill visa användarnamnet för alla användare som gillade ett inlägg. Med modellen ovan skulle det vara en enda, ganska snabb fråga:
db.post_likes.find(
{"postId":someValue},
{_id:0,user_name:1}
)
Med endast ID:n lagrade skulle denna ganska vanliga uppgift behöva minst två frågor och - med tanke på begränsningen att det kan finnas ett oändligt antal som gillar ett inlägg - potentiellt enormt minnesförbrukning (du skulle behöva lagra användar-ID:n i RAM).
Visst leder detta till viss redundans, men även när miljontals människor gillar ett inlägg talar vi bara om några få megabyte relativt billigt (och lätt skalbart) diskutrymme samtidigt som vi får mycket prestanda när det gäller användarupplevelse.
Nu kommer grejen:Även om användarnamnen och inläggstitlarna kan ändras, behövde du bara göra en multiuppdatering:
db.post_likes.update(
{"post_id":someId},
{ $set:{ "post_title":newTitle} },
{ multi: true}
)
Du handlar att det tar ett tag att göra några ganska sällsynta saker som att ändra ett användarnamn eller ett inlägg för extrem hastighet för användningsfall som händer extremt ofta.
Botta på raden
Tänk på att MongoDB är en dokumentorienterad databas. Så dokumentera händelserna du är intresserad av med de värden du behöver för framtida frågor och modellera dina data därefter.