Permettez-moi de dire d'emblée que je sais que ce n'est pas la meilleure solution. Je sais que c'est maladroit et que c'est une fonction pirate. Mais c'est pour ça que je suis là !
Cette question/ce travail s'appuie sur une discussion sur Quora avec Andrew Bosworth le créateur du fil d'actualité de Facebook.
Je crée un flux d'informations en quelque sorte. C'est construit uniquement en PHP
et MySQL
.
L'application MySQL
Le modèle relationnel de l'alimentation est composé de deux tables. Une table fonctionne comme un journal d'activité ; en fait, elle est nommée activity_log
. L'autre table est newsfeed
. Ces tables sont presque identiques.
Le site schéma pour le journal est activity_log(uid INT(11), activity ENUM, activity_id INT(11), title TEXT, date TIMESTAMP)
...et le schéma pour le flux est newsfeed(uid INT(11), poster_uid INT(11), activity ENUM, activity_id INT(11), title TEXT, date TIMESTAMP)
.
Chaque fois qu'un utilisateur fait quelque chose en rapport avec le fil d'actualité, par exemple en posant une question, il sera enregistré dans le journal d'activité immédiatement.
Génération des flux d'informations
Puis toutes les X minutes (5 minutes pour le moment, passera à 15-30 minutes plus tard), J'exécute un travail cron qui exécute le script ci-dessous. Ce script boucle sur tous les utilisateurs de la base de données, trouve toutes les activités de tous les amis de cet utilisateur, puis écrit ces activités dans le fil d'actualité.
Pour l'instant, le SQL
qui élimine l'activité (appelée en ActivityLog::getUsersActivity()
) a un LIMIT 100
imposée pour des raisons de performance*. *Non pas que je sache de quoi je parle.
<?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']);
}
}
}
}
Affichage des flux d'actualités
Dans le code client, lorsque je récupère le fil d'actualité de l'utilisateur, je fais quelque chose comme.. :
$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'];
}
Améliorer le fil d'actualité
Maintenant, pardonnez ma compréhension limitée des meilleures pratiques pour développer un fil d'actualité, mais je comprends que l'approche que j'utilise est une version limitée de ce que l'on appelle fan-out sur l'écriture Le projet est limité dans le sens où j'exécute une tâche cron comme étape intermédiaire au lieu d'écrire directement dans le fil d'actualité des utilisateurs. Mais c'est très différent d'un modèle pull, dans le sens où le fil d'actualité de l'utilisateur n'est pas compilé à la charge, mais plutôt de façon régulière.
C'est une grande question qui mérite probablement une grande quantité d'allers-retours, mais je pense qu'elle peut servir de pierre de touche pour de nombreuses conversations importantes que les nouveaux développeurs comme moi doivent avoir. J'essaie juste de comprendre ce que je fais mal, comment je peux m'améliorer, ou comment je devrais peut-être même repartir de zéro et essayer une approche différente.
Une autre chose qui me gêne dans ce modèle est qu'il fonctionne sur la base de la récence plutôt que de la pertinence. Si quelqu'un peut suggérer comment l'améliorer pour y intégrer la pertinence, je suis tout ouïe. J'utilise l'API de Directed Edge pour générer des recommandations, mais il semble que pour quelque chose comme un flux d'actualités, les recommandations ne fonctionnent pas (puisque rien n'a été favorisé auparavant !).
0 votes
Quoi ? Pas d'image humoristique attachée cette fois-ci ? Vous pouvez faire mieux que ça ! :P
0 votes
@alex Oh, mec, tu as raison. Je dois être en train de vieillir.
1 votes
@Josh Essayez ceci :)
0 votes
@alex Je vais devoir le faire maintenant. Espèce de tentatrice.
0 votes
@alex, Si cela vous intéresse, j'ai modifié ce texte pour ajouter un lien vers une discussion intéressante sur Quora avec Andrew Bosworth, dont ce travail s'est inspiré. quora.com/
0 votes
@alex, vous êtes 3 pour 3 ce soir.
0 votes
Josh : 3 sur 3 ? Mon cerveau du vendredi après-midi ne calcule pas...
0 votes
@alex, cela signifie 3 succès sur 3 tentatives.
0 votes
L'un des inconvénients de l'utilisation d'ENUM est que si vous souhaitez ajouter de nouveaux types d'activité, vous devrez effectuer un ALTER table, ce qui sera prohibitif si vous avez un grand nombre de lignes. (une table ALTER verrouille la table pour les écritures, et pendant une partie du processus, elle permet les lectures).
0 votes
@Cody, je ne connaissais pas cette histoire de
ENUM
. Avez-vous une autre solution à proposer ?1 votes
@Josh Smith est-ce que chaque utilisateur a un tableau de newsfeed ?
1 votes
@josh smith Si vous reconstruisez votre algorithme ci-dessus, veuillez le publier. Merci
1 votes
@JoshSmith, exécutez-vous une requête SQL pour chaque ami afin de saisir leurs activités ?
1 votes
J'essaie de créer un flux de nouvelles basé sur les utilisateurs qui suivent. Un utilisateur peut avoir des milliers de followers. Mon idée est de créer une table séparée pour chaque utilisateur (lorsque l'utilisateur s'enregistre) qui stockera l'activité de tous les utilisateurs qu'il suivra. Ma question est la suivante : lorsqu'une personne appuie sur le bouton "J'aime" et qu'elle a, disons, 1000 followers. Pour stocker les données dans le "tableau d'alimentation" de chaque suiveur, je vais utiliser une boucle foreach. L'utilisation de la boucle foreach est-elle bonne ou mauvaise ? Que se passe-t-il si la boucle se casse et ne répond plus ? Si l'utilisateur a un nombre élevé de followers, la boucle foreach peut prendre trop de temps pour chaque activité effectuée par l'utilisateur. Une solution ?
0 votes
Peut-être en utilisant une table de jonction, puis un identifiant d'utilisateur dans (les identifiants des amis).