Tvärtom, lösning 1 och 2 är din bästa insats. Lösning 3 kan övervägas när uppdaterings-/skapningsfrekvensen är mycket mindre jämfört med läsfrekvensen för projekt och användare, som även om det krävs två frågor för att uppdatera/skapa, och det är lätt att läsa det.
För att välja mellan lösning 1 och 2 måste du ta hänsyn till läsfrekvenserna. Kommer du att behöva projekt av en användare eller användningar av ett projekt oftare och välj efter det. Om du känner att båda är av relativt samma frekvens är det bättre att hålla användarobjektet så mindre klustrade som möjligt. Oavsett vilket alternativ du väljer, överväg att behålla ett index
på arrayen som lagrar _id
s (av projekt eller användare).
Till exempel.
userSchema = new Schema(
{//otherstuff
project_ids: [{type: Schema.Types.ObjectId, ref: 'Project'}})
...
})
userSchema.index({'project_ids':1})
eller
projectSchema = new Schema(
{//otherstuff
user_ids: [{type: Schema.Types.ObjectId, ref: 'User'}})
...
})
projectSchema.index({'user_ids':1})
Att hålla ett index på arrayen _id
kommer att avsevärt förbättra dina frågors hastighet på den sida där du fruktar att det kommer att bli betydande omkostnader.
Men behåll index
bara om denna relation är en viktig relation med många frågor på gång. Om detta bara är en sidofunktion i ditt projekt kan du göra det without
ett index också.
Om användaren kan göra massor av saker och har många relationer, kommer du att behöva det användarobjektet konstant i hela din app, så om din app inte är projektspecifik är det bättre att inte lägga in projekt-id:t i användarschemat . Men eftersom vi bara lägger in id:erna är det inte mycket av en overhead ändå. Du behöver inte oroa dig för det.
Reg index på båda arrayerna:Ja det kan du självklart. Men när du går för lösning 3 behöver du inte ett index alls eftersom du inte kommer att göra en fråga för att få listan över projekt för en användare eller listan över användare i ett projekt. Lösning 3 gör läsningen väldigt enkel men att skriva lite krångligt. Men som du nämnde att ditt användningsfall involverar reading>>writing
, gå med lösning 3 men det finns alltid en risk för datainkonsekvens som du måste ta hand om.
Indexering gör bara saker snabbare. Gå igenom dokumenten och googla lite. Inget märkvärdigt. Att fråga över indexerade arrayer är effektivt än vanliga arrayer. Till exempel. Låt oss anta att du använder lösning 2. Lagra projekt-id:t i fältet project_ids.
Du kan enkelt få en användares projekt. Det här är rakt fram.
Men för att få användare av project1. Du behöver en fråga som denna.
User.find({project_ids:project._id},function(err,docs){
//here docs will be the list of the users of project1
})
//The above query might be slow if the user base is large.
//But it can be improved vastly by indexing the project_ids field in the User schema.
Liknande för lösning 1. Varje projekt har user_ids-fält. Låt oss anta att vi har en användare1. För att få användarens projekt gör vi följande fråga
Project.find({user_ids:user1._id},function(err,docs){
//here docs will be the projects of user1
//But it can be improved vastly by indexing the user_ids field in the Project schema.
Om du funderar över lösning 1 vs lösning 2, är lösning 1 bättre antar jag. Det kan finnas fall där du behöver användare utan hans projekt men chansen att kräva projektet utan användare är ganska låg. Men det beror på ditt exakta användningsfall.