Lassen Sie mich gleich sagen, dass ich weiß, dass dies nicht die beste Lösung ist. Ich weiß, es ist klobig und ein Hack eines Features. Aber deshalb bin ich hier!
Diese Frage / Arbeit baut auf einer Diskussion über Quora mit Andrew Bosworth auf , dem Schöpfer des Facebook-Newsfeeds.
Ich baue eine Art Newsfeed. Es ist nur in PHP
und gebaut MySQL
.
Das MySQL
Das relationale Modell für den Feed besteht aus zwei Tabellen. Eine Tabelle fungiert als Aktivitätsprotokoll. in der Tat ist es benannt activity_log
. Die andere Tabelle ist newsfeed
. Diese Tabellen sind nahezu identisch.
Das Schema für das Protokoll lautetactivity_log(uid INT(11), activity ENUM, activity_id INT(11), title TEXT, date TIMESTAMP)
... und das Schema für den Feed lautet newsfeed(uid INT(11), poster_uid INT(11), activity ENUM, activity_id INT(11), title TEXT, date TIMESTAMP)
.
Jedes Mal, wenn ein Benutzer etwas für den Newsfeed relevantes tut , beispielsweise eine Frage stellt, wird er sofort im Aktivitätsprotokoll protokolliert .
Generieren der Newsfeeds
Dann führe ich alle X Minuten (im Moment 5 Minuten, später 15 bis 30 Minuten) einen Cron-Job aus , der das folgende Skript ausführt. Dieses Skript durchläuft alle Benutzer in der Datenbank, findet alle Aktivitäten für alle Freunde dieses Benutzers und schreibt diese Aktivitäten in den Newsfeed.
Im Moment hat das SQL
, was die Aktivität auswählt (aufgerufen ActivityLog::getUsersActivity()
) LIMIT 100
, aus Leistungsgründen * auferlegt. * Nicht, dass ich wüsste, wovon ich spreche.
<?php
$user = new User();
$activityLog = new ActivityLog();
$friend = new Friend();
$newsFeed = new NewsFeed();
// Get all the users
$usersArray = $user->getAllUsers();
foreach($usersArray as $userArray) {
$uid = $userArray['uid'];
// Get the user's friends
$friendsJSON = $friend->getFriends($uid);
$friendsArray = json_decode($friendsJSON, true);
// Get the activity of each friend
foreach($friendsArray as $friendArray) {
$array = $activityLog->getUsersActivity($friendArray['fid2']);
// Only write if the user has activity
if(!empty($array)) {
// Add each piece of activity to the news feed
foreach($array as $news) {
$newsFeed->addNews($uid, $friendArray['fid2'], $news['activity'], $news['activity_id'], $news['title'], $news['time']);
}
}
}
}
Anzeigen der Newsfeeds
Im Client-Code mache ich beim Abrufen des Newsfeeds des Benutzers Folgendes:
$feedArray = $newsFeed->getUsersFeedWithLimitAndOffset($uid, 25, 0);
foreach($feedArray as $feedItem) {
// Use a switch to determine the activity type here, and display based on type
// e.g. User Name asked A Question
// where "A Question" == $feedItem['title'];
}
Verbesserung des Newsfeeds
Verzeihen Sie jetzt mein begrenztes Verständnis der Best Practices für die Entwicklung eines Newsfeeds, aber ich verstehe, dass der Ansatz, den ich verwende, eine eingeschränkte Version des sogenannten Fan-Out beim Schreiben ist , begrenzt in dem Sinne, dass ich einen Cron-Job ausführe als Zwischenschritt, anstatt direkt in die Newsfeeds der Benutzer zu schreiben. Dies unterscheidet sich jedoch stark von einem Pull-Modell in dem Sinne, dass der Newsfeed des Benutzers nicht beim Laden, sondern regelmäßig kompiliert wird.
Dies ist eine große Frage, die wahrscheinlich viel Hin und Her verdient, aber ich denke, sie kann als Prüfstein für viele wichtige Gespräche dienen, die neue Entwickler wie ich führen müssen. Ich versuche nur herauszufinden, was ich falsch mache, wie ich mich verbessern kann oder wie ich vielleicht sogar von vorne anfangen und einen anderen Ansatz ausprobieren sollte.
Eine andere Sache, die mich an diesem Modell stört, ist, dass es eher auf Aktualität als auf Relevanz basiert. Wenn jemand vorschlagen kann, wie dies verbessert werden kann, um die Relevanz zu verbessern, wäre ich ganz Ohr. Ich verwende die API von Directed Edge zum Generieren von Empfehlungen, aber es scheint, dass für so etwas wie einen Newsfeed Empfehlungen nicht funktionieren (da bisher nichts bevorzugt wurde!).