MongoDB passar i allmänhet inte bra för att modellera grafrelationer. Det finns specialiserade grafdatabaser som utmärker sig för denna uppgift.
Men när du inte vill lägga till en annan databasteknik till mixen, skulle jag rekommendera att skapa en ny samling frienships
och modellera varje vänrelation som ett dokument med en uppsättning av två poster, var och en av dem ett objekt med den förkortade informationen om en av användarna som du behöver för att visa en post i dina vänlistor:
{
friendship: [
{
id:123,
name: "Bob",
avatar: "Bob.jpg"
},
{
id:456,
name: "Alice",
avatar: "Alice.jpg"
}
]
}
Skälet till att duplicera information från användardokumenten i vänskapsdokumenten är att undvika en andra fråga till användarens samling för att få all data för att visa en användarens vänlista. MongoDB kan inte göra JOINs kan endast utföra JOINs på odelade samlingar
, så du bör undvika att sprida data du behöver för ett specifikt användningsfall över flera samlingar, även när det innebär att du skapar övertalighet. Annars skulle du behöva utföra flera frågor efter varandra, vilket saktar ner svarstiden för din ansökan avsevärt.
När du vill hämta vänlistan för användare 123, utför du en db.friendships.find({"friendship.id", 123})
(ett index på friendship.id
kommer att förbättra prestandan) och får sedan en lista med dokument där Bob är antingen den första eller den andra vännen.
Du skulle sedan iterera dessa dokument och mata ut den korta informationen om array-posten som inte är användare 123.
Alternativt kan du filtrera bort Bob-posterna i databasen med en aggregeringspipeline. Använd $match-frågan ovan, $avveckla vänskapsarrayen och $matcha sedan de dokument där id inte är 123. Detta skulle vara en avvägning:Du sparar bandbredd på bekostnad av CPU-belastning på databasservern.
För att fråga om en vänskapsrelation redan existerar, använd:
db.friendships.find( { $and: [
{ "friendship.id": 123 },
{ "friendship.id": 456 }
] } ).count();