Comment puis-je mettre en œuvre les commentaires filetés?
je développe une application web qui peut supporter les commentaires threadés. J'ai besoin de pouvoir réorganiser les commentaires en fonction du nombre de votes reçus. (Identique à la façon dont les commentaires filetés fonctionnent dans reddit)
j'aimerais entendre les entrées de la communauté sur la façon de le faire.
Comment dois-je concevoir le commentaires table? Voici la structure que j'utilise maintenant:
Comment
id
parent_post
parent_comment
author
points
Quels changements doivent être fait à ce structure?
Comment puis-je obtenir les détails de ce tableau pour les afficher correctement? (Mise en œuvre dans n'importe quelle langue est la bienvenue. Je veux juste savoir comment le faire de la meilleure manière possible)
quelles sont les choses que je dois prendre soin tout en mettant en œuvre cette fonctionnalité afin qu'il y ait moins de charge sur le CPU/base de données?
Merci d'avance.
4 réponses
stocker des arbres dans une base de données est un sujet qui a beaucoup de solutions différentes. Cela dépend si vous souhaitez récupérer un subhierarchy (ainsi que tous les enfants de l'élément X) ou si vous voulez juste de saisir l'ensemble des hiérarchies et construire l'arbre dans un O(n) dans la mémoire à l'aide d'un dictionnaire.
Votre tableau a l'avantage que vous pouvez récupérer tous les commentaires sur un post en 1 go, en filtrant sur l'parentpost. Comme vous avez défini le parent du commentaire dans le manuel / manière naïve, vous construire l'arbre en mémoire (voir ci-dessous). Si vous voulez obtenir l'arbre à partir de la base de données, vous avez besoin d'une autre façon de stocker un arbre: Voir ma description d'une approche basée pré-calc ici: http://www.llblgen.com/tinyforum/GotoMessage.aspx?MessageID=17746&ThreadID=3208 ou par utilisation d'arbres équilibrés décrits par CELKO ici:
ou encore une autre approche: http://www.sqlteam.com/article/more-trees-hierarchies-in-sql
si vous allez chercher le tout dans une hiérarchie dans la mémoire, et construire l'arbre, il peut être plus efficace en raison du fait que la requête est assez simple: sélectionnez .. from Comment where ParentPost = @id ORDER BY ParentComment ASC
après cette requête,vous construisez l'arbre en mémoire avec juste un dictionnaire qui garde la trace du Commentaire de tuple. Vous marchez maintenant à travers le jeu de résultats et construisez l'arbre à la volée: chaque commentaire que vous rencontrez, vous pouvez rechercher son commentaire parent dans le dictionnaire et puis stocker le commentaire actuellement traité aussi dans ce dictionnaire.
deux choses à considérer également...
1) Quand vous dites "trier comme reddit" basée sur le rang ou la date, voulez-vous dire le niveau supérieur ou le tout?
2) Quand vous supprimez un noeud, qu'arrive-t-il aux branches? Avez-vous re-parent? Dans mon implémentation, je pense que les éditeurs vont décider -- soit cacher le noeud et l'afficher comme "commentaire caché" avec les enfants visibles, cacher le commentaire et ce sont les enfants, ou atomiser l'arbre entier. Re-parenting devrait être facile (il suffit de mettre le parent du chidren au parent du supprimé), mais tout ce qui concerne l'arbre entier semble difficile à mettre en œuvre dans la base de données.
j'ai été à la recherche à l' itree module pour PostgreSQL. Il devrait rendre les opérations de base de données impliquant des parties de l'arbre un peu plus rapides. Il vous permet essentiellement de configurer un champ dans la table qui ressemble à:
ltreetest=# select path from test where path <@ 'Top.Science';
path
------------------------------------
Top.Science
Top.Science.Astronomy
Top.Science.Astronomy.Astrophysics
Top.Science.Astronomy.Cosmology
cependant, il ne garantit pas d'intégrité référentielle en soi. En d'autres termes, vous pouvez avoir un enregistrement pour "Top.Sciences.L'astronomie" sans avoir un enregistrement de "Top.Science " ou "Top". Mais il vous permet de faire des choses comme:
-- hide the children of Top.Science
UPDATE test SET hide_me=true WHERE path @> 'Top.Science';
ou
-- nuke the cosmology branch
DELETE FROM test WHERE path @> 'Top.Science.Cosmology';
si combiné avec la traditionnelle approche"comment_id"/" parent_id " en utilisant des procédures stockées, je pense que vous pouvez obtenir le meilleur des deux mondes. Vous pouvez rapidement parcourir l'arborescence des commentaires dans la base de données en utilisant votre "chemin" et encore assurer l'intégrité référentielle via "comment_id" / "parent_id". J'envisage quelque chose comme:
CREATE TABLE comments (
comment_id SERIAL PRIMARY KEY,
parent_comment_id int REFERENCES comments(comment_id) ON UPDATE CASCADE ON DELETE CASCADE,
thread_id int NOT NULL REFERENCES threads(thread_id) ON UPDATE CASCADE ON DELETE CASCADE,
path ltree NOT NULL,
comment_body text NOT NULL,
hide boolean not null default false
);
La chaîne de chemin pour un commentaire ressembler à
<thread_id>.<parent_id_#1>.<parent_id_#2>.<parent_id_#3>.<my_comment_id>
ainsi un commentaire racine du thread " 102 " avec un comment_id de "1" aurait un chemin de:
102.1
Et un enfant dont les comment_id est "3" serait:
102.1.3
A certains enfants de "3" ayant des pièces d'identité de "31" et "54" seraient:
102.1.3.31
102.1.3.54
pour cacher le noeud " 3 " et son les enfants, vous feriez question:
UPDATE comments SET hide=true WHERE path @> '102.1.3';
Je ne sais pas cependant -- cela pourrait ajouter des frais généraux inutiles. En Plus je ne sais pas comment bien entretenues ltree est.
Votre conception actuelle est fondamentalement fine pour les petites hiérarchies (moins de mille articles)
si vous voulez récupérer sur un niveau ou une profondeur certian, ajoutez un élément' level ' à votre structure et calculez - le dans le cadre de la sauvegarde
si la performance est un problème utilisez un cache décent
j'ajouterais les nouveaux champs suivants au tabel ci-dessus:
thread_id: identifiant pour tous les commentaires attachés à un objet spécifique
date: la date du commentaire (permet de récupérer les commentaires dans l'ordre)
rank: the comment rank (permet de récupérer l'ordre des commentaires par classement)
en utilisant ces champs vous pourrez:
- extraction de tous les commentaires dans un thread dans un seul op
- commander des commentaires dans un thread soit par date soit par rang
malheureusement si vous voulez préserver vos requêtes DB proche de la norme SQL, vous devrez recréer l'arbre en mémoire. Certaines banques de données offrent des requêtes spéciales pour les données hiérarchiques (F. E. Oracle)
./alex