2012-06-08 2 views
7

Je viens d'avoir une question générale sur la théorie des bases de données. J'ai besoin de faire quelque chose de similaire à montrer quels articles/articles un utilisateur a vu ou non (comme dans un forum) ou un message électronique non lu. Ce que j'ai, c'est qu'il y a des messages que plusieurs utilisateurs peuvent voir, mais il doit séparer par utilisateur qui l'a réellement vu. Ainsi, si l'utilisateur A consultait le message 1, il ne montrerait plus que le message 1 est un nouvel élément à afficher, mais à l'utilisateur B, il indiquerait toujours que le message 1 est un nouvel élément à afficher. Je cherche d'autres idées et l'une d'entre elles consiste à obtenir un horodatage de la dernière connexion de l'utilisateur, mais je dois en fait suivre les publications qu'ils ont vues, par opposition aux messages postés depuis leur dernière connexion.Comment structurer la base de données pour les alertes d'éléments non lus par utilisateur

Je voudrais une solution de base de données MySQL si possible, mais je suis ouvert aux cookies si c'est un must. Je pourrais le faire moi-même et juste le comprendre, mais j'apprécierais tous les conseils sur la façon de structurer correctement une table (s) pour le rendre le plus efficace. En outre, la bande passante et le stockage ne sont pas un problème.

+1

Vous pourriez jeter un coup d'oeil à la façon dont vBulletin et d'autres systèmes de forum le manipulent, pour avoir une idée. Ou peut-être [phpBB] (http://www.phpbb.com/), puisque je suppose que vous devez acheter vBulletin. –

Répondre

6

Lors de l'examen du relevant schema for phpBB, je trouve ce qui suit:

# Table: 'phpbb_topics_track' 
CREATE TABLE phpbb_topics_track (
    user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, 
    topic_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, 
    forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, 
    mark_time int(11) UNSIGNED DEFAULT '0' NOT NULL, 
    PRIMARY KEY (user_id, topic_id), 
    KEY topic_id (topic_id), 
    KEY forum_id (forum_id) 
) CHARACTER SET `utf8` COLLATE `utf8_bin`; 

Et:

# Table: 'phpbb_forums_track' 
CREATE TABLE phpbb_forums_track (
    user_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, 
    forum_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, 
    mark_time int(11) UNSIGNED DEFAULT '0' NOT NULL, 
    PRIMARY KEY (user_id, forum_id) 
) CHARACTER SET `utf8` COLLATE `utf8_bin`; 

Je look here in their wiki:

Ce tableau tient un registre des sujets visités afin de marquez-les comme lu ou non lu. Nous utilisons l'horodatage mark_time conjointement avec dernier message de l'horodatage du sujet x pour savoir si le sujet x est lu ou non. Pour savoir exactement si un sujet est lu, il faut également vérifier phpbb_forums_track.

Donc, essentiellement, ils ont une table de consultation pour stocker les données associées à la visualisation d'un sujet (fil) d'un utilisateur, puis vérifiez contre l'horodatage dans le tableau d'affichage du forum, afin de déterminer si le sujet a été vu par l'utilisateur.

+0

C'est exactement ce dont j'avais besoin. Je vais juste créer la table phpbb_forums_track et cela devrait faire le travail dont j'ai besoin. Merci – n0nag0n

+1

Pas de problème. J'allais publier l'emplacement de la requête qui accède aux données aussi. Je vous ferai savoir si je le trouve. –

+1

Considérez également que vous allez probablement vouloir mettre en cache les données dans la session de l'utilisateur sur le serveur, de sorte que vous appelez constamment cette requête (qui est probablement lente). Ensuite, construisez des fonctionnalités pour pousser les données de vue vers le cache en même temps qu'il est enregistré dans la base de données. –

2

Il suffit de créer une simple table de référence croisée (read_posts ou quelque chose):

user_id|post_id 
---------------- 
2  | 132 
53  | 43 
.... 

Assurez-vous que ces deux colonnes sont indexées (particulièrement important que le user_id indexé), puis utiliser une jointure (ou une sous-requête) pour sélectionner les messages non lus pour l'utilisateur connecté. Si vous êtes juste essayer de montrer une liste de messages non lus, par exemple, vous exécutez simplement:

SELECT * FROM `posts` WHERE `post_id` NOT IN (
    SELECT `post_id` FROM `read_posts` WHERE `user_id`='[$USER ID]') 
ORDER BY [your ordering clause] 
+1

Les performances d'une sous-sélection et d'une clause IN ne seraient-elles pas problématiques pour quelque chose comme la vérification des pages vues? Sauf bien sûr, il y avait une mise en cache de ces données dans la session utilisateur. –

+1

Les sous-requêtes sont potentiellement beaucoup moins efficaces que les jointures, mais je pense que dans ce cas il n'y aurait pas de hit de la sous-requête ... les sous-requêtes complexes ne "choisissent" pas l'ordre d'exécution le plus efficace. Il n'y a pas d'ambiguïté et les performances devraient être parfaites même avec un grand nombre de lignes - en particulier avec l'utilisation correcte de l'indexation. Si vous avez quelques repères qui suggèrent une jointure serait plus rapide dans ce cas, je serais très intéressé. –

+0

Vous avez raison, je crois. J'utiliserais probablement un 'JOIN ', mais cela pourrait être plus préféré. Quoi qu'il en soit, je pense que la meilleure approche est une combinaison de mise en cache de sessions et de mises à jour de double cache/session lorsque l'utilisateur consulte un article/sujet. Ainsi, la requête ne s'exécute réellement que pendant un processus de connexion ou une configuration de session, ce qui serait efficace et gérable. –

1

Sur la base de cette description je voudrais utiliser une table simple avec peut-être trois colonnes.

  1. ID utilisateur
  2. Poster ID
  3. Timestamp Première Vu

Lorsqu'un utilisateur affiche un message, ajouter une ligne à la table. Si une ligne n'existe pas dans la table pour un combo utilisateur/post-ID donné, alors ils n'ont pas vu le message.

Questions connexes