Zunächst einmal ist „Wörterbuch in der Benutzerklasse“ keine gute Idee. warum? Das Hinzufügen eines zusätzlichen Tarifobjekts erfordert, dass ein neues Element in das Array verschoben wird, was bedeutet, dass das alte Element entfernt wird, und dieses Einfügen wird als "Dokument verschieben" bezeichnet ". Das Verschieben von Dokumenten ist langsam und MongoDB ist nicht so gut darin, leeren Speicherplatz wiederzuverwenden, sodass das häufige Verschieben von Dokumenten zu großen Schwaden leerer Datendateien führen kann (einige Texte im Buch "MongoDB The Definitive Guide").
Was ist dann die richtige Lösung:Angenommen, Sie haben eine Sammlung namens Blogs und möchten eine Bewertungslösung für Ihre Blog-Posts implementieren und zusätzlich alle benutzerbasierten Bewertungsvorgänge verfolgen.
Das Schema für ein Blog-Dokument würde wie folgt aussehen:
{
_id : ....,
title: ....,
....
rateCount : 0,
rateValue : 0,
rateAverage: 0
}
Sie benötigen eine weitere Sammlung (Raten) mit diesem Dokumentschema:
{
_id: ....,
userId: ....,
postId:....,
value: ..., //1 to 5
date:....
}
Und Sie müssen einen geeigneten Index dafür definieren:
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
Wenn ein Benutzer eine Bewertung abgeben möchte, müssen Sie zunächst prüfen, ob der Benutzer den Beitrag bewertet hat oder nicht. davon aus, dass der Benutzer 'user1'
ist , die Abfrage wäre dann
var ratedBefore = db.Rates.find({userId : 'user1', postId : 'post1'}).count()
Und basierend auf ratedBefore
, wenn !ratedBefore
Fügen Sie dann ein neues Bewertungsdokument in die Bewertungssammlung ein und aktualisieren Sie den Blogstatus, andernfalls darf der Benutzer nicht bewerten
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}});
}
Was wird dann mit rateAverage
passieren? ?Ich empfehle dringend, es basierend auf rateCount
zu berechnen und rateValue
Auf der Client-Seite ist es einfach, rateAverage
zu aktualisieren mit mongoquery
, aber du solltest es nicht tun. warum? Die einfache Antwort lautet:Dies ist eine sehr einfache Aufgabe für den Kunden, diese Art von Arbeiten zu handhaben, und das Setzen eines Durchschnittswerts für jedes Blog-Dokument erfordert eine unnötige Aktualisierungsoperation.
Die durchschnittliche Abfrage würde wie folgt berechnet:
var blog = db.Blog.findOne({"_id" : "post1"});
var avg = blog.rateValue / blog.rateCount;
print(avg);
Mit diesem Ansatz erhalten Sie maximale Leistung mit mongodb und Sie haben den Überblick über jede Rate basierend auf Benutzer, Beitrag und Datum.