Schema für Benutzerbewertungen - Schlüssel / Wert-DB

8

Wir verwenden MongoDB und ich finde ein Schema zum Speichern von Ratings.

  • Bewertungen haben Werte von 1-5.
  • Ich möchte andere Werte wie fromUser speichern

Das ist in Ordnung, aber die Hauptfrage, die ich habe, besteht darin, es so einzurichten, dass die Berechnung des Durchschnitts so effizient wie möglich ist.

LÖSUNG 1 - Getrennte Bewertungsklasse

Der erste Gedanke war, eine separate Klasse Ratings zu erstellen und ein Array von Zeigern auf Ratings in der Klasse User zu speichern. Der Grund, warum ich das einmal vermutet habe, ist, dass wir jedes Mal, wenn ein neues Ratings hereinkommt, nach allen Rating -Objekten fragen müssen, damit wir einen Durchschnittswert berechnen können

...

LÖSUNG 2 - Wörterbuch in Benutzerklasse

Der zweite Gedanke war, ein Wörterbuch direkt in der Klasse User zu speichern, das diese Ratings -Objekte speichern würde. Dies wäre etwas leichter als Lösung 1, aber wir würden den gesamten Ratings Verlauf jedes Benutzers bei jedem Update neu schreiben. Das scheint gefährlich.

...

LÖSUNG 3 - Separate Bewertungsklasse mit separaten Durchschnitten in Benutzerklasse

Hybrid-Option, wo wir Ratings in ihrer eigenen Klasse haben, und ein Zeiger-Array für sie, aber wir behalten zwei Werte in der Benutzerklasse - ratingsAve und ratingsCount . Auf diese Weise speichern wir das Objekt, wenn ein neues Rating festgelegt wurde, aber wir können das ratingsAve einfach neu berechnen.

LÖSUNG 3 hört sich für mich am besten an, aber ich frage mich nur, ob wir regelmäßige Kalibrierungen einbeziehen müssen, indem Sie den Bewertungsverlauf erneut aufrufen, um ratingsAve zurückzusetzen, nur um sicherzustellen, dass alles überprüft wird.

Ich könnte das überdenken, aber ich bin nicht so toll bei der Erstellung von DB-Schemas, und das scheint ein Standardschema-Problem zu sein, das ich umsetzen sollte.

Welche ist die beste Option, um Konsistenz sicherzustellen, aber auch die Effizienz der Neuberechnung?

    
Ramsel 13.11.2014, 17:05
quelle

3 Antworten

16

Zunächst einmal ist 'Dictionary in User Class' keine gute Idee. Warum? Wenn Sie ein zusätzliches Ratenobjekt hinzufügen, müssen Sie ein neues Element in das Array verschieben, was bedeutet, dass das alte Objekt entfernt wird. Diese Einfügung wird " Verschieben eines Dokuments " genannt. Das Verschieben von Dokumenten ist langsam und MongoDB ist nicht so gut in der Wiederverwendung von leerem Speicherplatz. Wenn Sie also Dokumente viel herum bewegen, kann dies zu großen Schwaden leerer Datendateien führen (etwas Text im Buch "MongoDB The Definitive Guide").

Was ist dann die richtige Lösung? Angenommen, Sie haben eine Sammlung mit dem Namen "Blogs" und möchten eine Bewertungslösung für Ihre Blogposts implementieren und zusätzlich jede benutzerbasierte Ratenoperation verfolgen.

Das Schema für ein Blogdokument wäre wie folgt:

%Vor%

Sie benötigen eine andere Sammlung (Preise) mit diesem Dokumentenschema:

%Vor%

Und Sie müssen einen passenden 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 Nutzer bewerten möchte, müssen Sie zunächst prüfen, ob der Nutzer den Beitrag bewertet hat oder nicht. Angenommen, der Benutzer ist 'user1' , dann wäre die Abfrage

%Vor%

Und basierend auf ratedBefore , wenn !ratedBefore , fügen Sie ein neues Tarifdokument in die Rates-Sammlung ein und aktualisieren Sie den Blog-Status, anderenfalls darf der Benutzer nicht bewerten

%Vor%

Was wird dann mit rateAverage passieren? Ich empfehle dringend, es auf der Grundlage von rateCount und rateValue auf der Client-Seite zu berechnen, es ist einfach, rateAverage mit mongoquery zu aktualisieren, aber Sie sollten es nicht tun. Warum? Die einfache Antwort lautet: Dies ist eine sehr einfache Aufgabe für den Kunden, um diese Art von Arbeiten zu erledigen und der Durchschnitt auf jedem Blog-Dokument benötigt eine unnötige Update-Operation.

Die durchschnittliche Abfrage würde wie folgt berechnet:

%Vor%

Mit diesem Ansatz erhalten Sie maximale Leistung mit mongodb und Sie verfolgen jede Rate basierend auf Benutzer, Post und Datum.

    
Disposer 24.11.2014 10:29
quelle
2

Ich würde es ein bisschen anders machen: Haben Sie eine Benutzerklasse und eine Ratingklasse und aggregieren Sie die Anzahl der Bewertungen und des Ratingdurchschnitts.

Die Bewertungsklasse

Das ist ein bisschen Pseudocode, aber die Bedeutung sollte offensichtlich sein.

%Vor%

Um die Aggregation effizient durchzuführen, sollten Sie mindestens einen Index über rated erstellen:

%Vor%

Sie können nun zwischen Ansätzen wählen: Entweder Sie berechnen die Anzahl der Bewertungen und den Durchschnitt, sagen wir einmal pro Stunde und speichern sie in einer Sammlung, sagen wir rate_averages , oder Sie berechnen diese Werte auf Anfrage / p>

Vorberechnet

%Vor%

Ein Dokument in der Sammlung rate_averages sieht dann so aus:

%Vor%

und kann einfach nach den Werten des einzelnen Benutzers abgefragt werden, da _id automatisch indiziert wird.

Auf Anfrage

Sie würden die gleiche Bewertung und fast die gleiche Aggregationsabfrage verwenden, außer dass wir eine $match stage hinzufügen, so dass wir nur mit den Werten für den Benutzer arbeiten, für den wir die Statistiken kennen und den $out weglassen wollen. Bühne und lassen Sie das Dokument direkt zurückgegeben werden:

%Vor%

würde ein einzelnes Dokument zurückgeben, wie es für den betreffenden Benutzer angezeigt wird.

Mit diesem Ansatz und einem geeigneten Datenmodell können Sie beispielsweise Folgendes tun: "Wie viele Bewertungen wurden von einem bestimmten Benutzer zu einem bestimmten Datum abgegeben?" oder "Was sind die aktivsten Bewerter / am meisten bewertet?" ziemlich leicht.

Lesen Sie die Aggregations-Framework-Dokumentation für weitere Details. Sie könnten auch die Datenmodellierungsdokumente nützlich finden.

    
Markus W Mahlberg 24.11.2014 11:22
quelle
1

Der Code unterhalb kann verwendet werden, um die durchschnittliche Bewertung für jeden Benutzer zu erhalten.

%Vor%     
SUNDARRAJAN K 25.11.2014 18:33
quelle

Tags und Links