Først og fremmest er 'Ordbog i brugerklasse' ikke en god idé. hvorfor? Tilføjelse af et ekstra satsobjekt kræver, at du skubber et nyt element til arrayet, hvilket betyder, at det gamle element vil blive fjernet, og denne indsættelse kaldes "flytning af et dokument ". Flytning af dokumenter er langsom, og MongoDB er ikke så god til at genbruge tom plads, så flytning af dokumenter kan resultere i store dele af tomme datafiler (noget tekst i 'MongoDB The Definitive Guide'-bogen).
Hvad er så den rigtige løsning:antag, at du har en samling ved navn Blogs, og ønsker at implementere en vurderingsløsning til dine blogindlæg, og derudover holde styr på hver brugerbaseret prisoperation.
Skemaet for et blogdokument ville være sådan:
{
_id : ....,
title: ....,
....
rateCount : 0,
rateValue : 0,
rateAverage: 0
}
Du har brug for en anden samling (priser) med dette dokumentskema:
{
_id: ....,
userId: ....,
postId:....,
value: ..., //1 to 5
date:....
}
Og du skal definere et korrekt indeks for det:
db.Rates.ensureIndex({userId : 1, postId : 1})// very useful. it will result in a much faster search operation in case you want to check if a user has rated the post previously
Når en bruger vil bedømme, skal du først tjekke, om brugeren har bedømt indlægget eller ej. antag, at brugeren er 'user1'
, ville forespørgslen derefter være
var ratedBefore = db.Rates.find({userId : 'user1', postId : 'post1'}).count()
Og baseret på ratedBefore
, hvis !ratedBefore
indsæt derefter et nyt takstdokument til Prisindsamling og opdater blogstatus, ellers har brugeren ikke lov til at vurdere
if(!ratedBefore)
{
var postId = 'post1'; // this id sould be passed before by client driver
var userId = 'user1'; // this id sould be passed before by client driver
var rateValue = 1; // to 5
var rate =
{
userId: userId,
postId: postId,
value: rateValue,
date:new Date()
};
db.Rates.insert(rate);
db.Blog.update({"_id" : postId}, {$inc : {'rateCount' : 1, 'rateValue' : rateValue}});
}
Hvad sker der så med rateAverage
?Jeg anbefaler kraftigt at beregne det baseret på rateCount
og rateValue
på klientsiden er det nemt at opdatere rateAverage
med mongoquery
, men du bør ikke gøre det. hvorfor? Det enkle svar er:dette er en meget nem opgave for klienten at håndtere denne slags arbejde, og at sætte gennemsnit på hvert blogdokument kræver en unødvendig opdatering.
den gennemsnitlige forespørgsel ville blive beregnet som:
var blog = db.Blog.findOne({"_id" : "post1"});
var avg = blog.rateValue / blog.rateCount;
print(avg);
Med denne tilgang vil du få maksimal ydeevne med mongodb og du har styr på hver pris baseret på bruger, indlæg og dato.