2009-06-22 7 views
12

Ich mache eine Digg-ähnliche Website, die eine Homepage mit verschiedenen Kategorien haben wird. Ich möchte die beliebtesten Einreichungen anzeigen.Popularität Algorithmus

Unser Bewertungssystem ist einfach "likes", wie "Ich mag das" und was nicht. Grundsätzlich möchten wir die Einsendungen mit der höchsten Anzahl von "Likes" pro Zeit anzeigen. Wir wollen drei Kategorien haben: Allzeitpopularität, letzte Woche und letzter Tag.

Kennt jemand eine Möglichkeit zu helfen? Ich habe keine Ahnung, wie ich das machen und effizient machen soll. Ich dachte, wir könnten alle 10 Minuten einen Cron-Job machen und die Anzahl der Likes in den letzten 10 Minuten ziehen ... aber mir wurde gesagt, dass das ziemlich ineffizient ist.

Hilfe?

Danke!

Antwort

9

Normalerweise gehen Digg und Reddit-ähnliche Websites nach dem Datum der Einreichung und nicht nach den Zeiten der Abstimmungen. Auf diese Weise genügt eine einfache SQL-Abfrage, um die besten Einsendungen für den Zeitraum X zu finden. Hier ist eine pseudo-Abfrage, um die 10 beliebtesten Links von den letzten 24 Stunden mit dieser Methode zu finden:

select * from submissions 
where (current_time - post_time) < 86400 
order by score desc limit 10 

Grundsätzlich ist diese Abfrage sagt alle Beiträge zu finden, wo die Anzahl der Sekunden zwischen jetzt und der Zeit, es war gepostet ist weniger als 86400, das ist 24 Stunden in UNIX-Zeit.

Wenn Sie wirklich Popularität Intervall innerhalb X Zeit messen wollen, werden Sie die Post und die Zeit für jede Stimme in einer anderen Tabelle speichern müssen:

create table votes (
post foreign key references submissions(id), 
time datetime, 
vote integer); -- +1 for upvote, -1 for downvote 

Dann können Sie eine Liste der beliebtesten erzeugen Beiträge zwischen X und Y Zeiten wie so:

select sum(vote), post from votes 
where X < time and time < Y 
group by post 
order by sum(vote) desc limit 10; 

von hier gibt es nur ein Katzen sind, überspringen und innere Verknüpfung zu den zurückgegebenen IDs ab, die Post-Daten gebunden entfernt.

+1

Ich schrieb im Grunde das Gleiche, du warst schneller als ich. =) –

+1

großartige Antwort ... es sieht so aus, obwohl die erste Methode, die Sie beschreiben, einfacher ist, behandelt es nicht den Fall, wo etwas, das eine Weile zurückgeschickt wurde plötzlich ein Wiederaufleben der Popularität sehen (vielleicht aufgrund einer kürzlichen Nachrichtenveranstaltung oder etwas)? Die zweite Methode sieht robuster aus, danke, ich werde es ausprobieren! –

-1

Um nobody_'s Antwort zu vervollständigen, würde ich vorschlagen, dass Sie auf der documentation lesen (wenn Sie MySQL natürlich verwenden).

3

Haben Sie ein anständiges DB-Setup? Können wir bitte etwas über Ihre CREATE TABLE Details und Indizes erfahren? Bei einer vernünftigen Konfiguration sollte die Datenbank in der Lage sein, die von Ihnen benötigten Zählerstände schnell genug an Ihre Anforderungen anzupassen! Zum Beispiel (nach Abzug von Indizes und Schlüssel, die etwas davon abhängen, welche DB-Engine Sie verwenden), da zwei Tabellen:

CREATE TABLE submissions (subid INT, when DATETIME, etc etc) 
CREATE TABLE likes (subid INT, when DATETIME, etc etc) 

Sie die Top 33 Allzeit beliebte Einreichungen als

bekommen
SELECT *, COUNT(likes.subid) AS score 
FROM submissions 
JOIN likes USING(subid) 
GROUP BY submissions.subid 
ORDER BY COUNT(likes.subid) DESC 
LIMIT 33 

und diejenigen für so

innerhalb eines bestimmten Zeitbereiches gewählt
SELECT *, COUNT(likes.subid) AS score 
FROM submissions 
JOIN likes USING(subid) 
WHERE likes.when BETWEEN initial_time AND final_time 
GROUP BY submissions.subid 
ORDER BY COUNT(likes.subid) DESC 
LIMIT 33 

Wenn Sie wurden „Stimmen“ (positiv oder negativ) in likes speichern, anstatt nur jeden Eintrag zu zählen dort als +1, könnten Sie einfach SUM(likes.vote) anstelle der COUNT s verwenden.

0

Für stabile Liste wie alltime, lastweek, weil sie nicht wirklich schnell ändern sollen, so dass ich denke, dass Sie die Liste in Ihrem Cache mit Ablaufzeit von ca. 1 Tag oder länger speichern sollten.

Wenn Sie sich um die korrekte Anzahl in Echtzeit kümmern, können Sie bei jeder Seitenansicht überprüfen, indem Sie die Seite mit der niedrigsten Seite im Cache vergleichen.

Alles, was Sie tun müssen, ist für die Synchronisierung zwischen dem Cache und der tatsächlichen Datenbank sorgen.

thethanghn

+0

Das Ziel meines Ansatzes ist es, so viele Datenbankabfragen wie möglich zu reduzieren, da Sie nicht ständig die oberste Datenbank abrufen müssen – thethanghn

0

Abfragen, wo die Reihenfolge eine Funktion der aktuellen Zeit ist, kann echte Performance-Probleme werden. Die Dinge werden viel einfacher, wenn Sie nach Kalenderzeit Bucket und aktualisieren Sie die Punktzahlen für jeden Eimer bei der Abstimmung.