Позвольте мне начать с места в карьер, сказав, что я знаю, что это не лучшее решение. Я знаю, это kludgy и взломать особенность. Но вот почему я здесь!
Этот вопрос/работа строится некоторое обсуждение Quora с Эндрю Босуортом, создателем новостной ленты Facebook.
Я создаю новостной ленту. Он построен исключительно в PHP
и MySQL
.
MySQL
Реляционная модель для фида состоит из двух таблиц. Одна таблица функционирует как журнал активности; Фактически, он назывался activity_log
. Другая таблица - newsfeed
. Эти таблицы почти идентичны.
Схема для журнала - activity_log(uid INT(11), activity ENUM, activity_id INT(11), title TEXT, date TIMESTAMP)
... и схема для фида newsfeed(uid INT(11), poster_uid INT(11), activity ENUM, activity_id INT(11), title TEXT, date TIMESTAMP)
.
В любое время, когда пользователь делает что-то, относящееся к новостному каналу, например, задавая вопрос, он будет немедленно зарегистрирован в журнале активности.
Создание новостных лент
Затем каждые X минут (через 5 минут будет изменено на 15-30 минут), Я запустил задание cron, которое выполняет script ниже, Этот script проходит через всех пользователей в базе данных, находит все действия для всех пользователей этого пользователя, а затем записывает эти действия в ленту новостей.
В настоящий момент SQL
, который отбирает активность (называемый ActivityLog::getUsersActivity()
), имеет аргумент LIMIT 100
, заданный для производительности *. * Не то, чтобы я знал, о чем говорю.
<?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 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']);
}
}
}
}
Отображение новостей
В коде клиента, когда вы выбираете ленту новостей пользователя, я делаю что-то вроде:
$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'];
}
Улучшение новостей
Теперь простите мое ограниченное понимание лучших практик разработки новостного канала, но я понимаю подход, который я использую, чтобы быть ограниченной версией того, что называется fan-out при записи, ограниченном в смысл, что я выполняю работу cron в качестве промежуточного шага вместо того, чтобы напрямую писать в новостные каналы пользователей. Но это сильно отличается от модели pull, в том смысле, что поток новостей пользователя не скомпилирован при загрузке, а скорее на регулярной основе.
Это большой вопрос, который, вероятно, заслуживает большого количества назад и вперед, но я думаю, что он может послужить пробным камнем для многих важных разговоров, которые должны иметь такие новые разработчики, как я. Я просто пытаюсь понять, что я делаю неправильно, как я могу улучшить, или как я должен даже начинать с нуля и попробовать другой подход.
Еще одна вещь, которая меня обманывает в этой модели, заключается в том, что она работает на основе релевантности, а не релевантности. Если кто-нибудь может предложить, как это можно улучшить, чтобы работать с релевантностью, я бы все уши. Я использую Directed Edge API для генерации рекомендаций, но, похоже, что-то вроде новостного канала, рекомендации не будут работать (так как раньше ничего не было!).