187 votes

Mise en œuvre des commentaires et des appréciations dans la base de données

Je suis un développeur de logiciels. J'adore coder, mais je déteste les bases de données... Actuellement, je suis en train de créer un site web sur lequel un utilisateur pourra marquer une entité comme étant a aimé (comme sur FB), étiquette et commentaire .

Je suis bloqué sur la conception des tables de base de données pour gérer cette fonctionnalité. La solution est triviale, si nous ne pouvons le faire que pour un seul type de chose (par exemple des photos). Mais j'ai besoin de l'activer pour 5 choses différentes (pour l'instant, mais je suppose aussi que ce nombre peut augmenter, à mesure que le service se développe).

J'ai trouvé des questions similaires ici, mais aucune n'a de réponse satisfaisante, alors je pose à nouveau cette question.

La question est de savoir comment le faire correctement, efficacement y élastiquement concevoir la base de données, afin qu'elle puisse stocker des commentaires pour différents tableaux , aime pour différents tableaux y tags pour eux. Un modèle de conception comme réponse serait le mieux ;)

Description détaillée : J'ai un tableau User avec quelques données utilisateur, et 3 autres tableaux : Photo con photographies , Articles con articles , Places con places . Je veux permettre à tout utilisateur connecté de :

  • commentaire sur l'un de ces 3 tableaux

  • marquer l'un d'entre eux comme aimé

  • étiqueter n'importe lequel d'entre eux avec une étiquette

  • Je veux également compter le nombre de likes pour chaque élément et le nombre de fois où ce tag particulier a été utilisé.

1 st approche :

a) Pour tags Je vais créer un tableau Tag [TagId, tagName, tagCounter] alors je vais créer plusieurs à plusieurs relations tableaux pour : Photo_has_tags , Place_has_tag , Article_has_tag .

b) Il en va de même pour les commentaires.

c) Je vais créer un tableau LikedPhotos [idUser, idPhoto] , LikedArticles[idUser, idArticle] , LikedPlace [idUser, idPlace] . Nombre de aime sera calculé par demandes de renseignements (ce qui, je suppose, est mauvais). Et...

Je n'aime vraiment pas ce design pour la dernière partie, ça sent mauvais pour moi ;)

2 et approche :

Je vais créer une table ElementType [idType, TypeName == some table name] qui sera rempli par l'administrateur (moi) avec les noms de tableaux qui peuvent être a aimé , comentó o Étiqueté . Ensuite, je vais créer tableaux :

a) LikedElement [idLike, idUser, idElementType, idLikedElement] et la même chose pour les commentaires et les étiquettes avec les colonnes appropriées pour chacun. Maintenant, quand je veux faire une photo aimée, je vais l'insérer :

typeId = SELECT id FROM ElementType WHERE TypeName == 'Photo'
INSERT (user id, typeId, photoId)

et pour les lieux :

typeId = SELECT id FROM ElementType WHERE TypeName == 'Place'
INSERT (user id, typeId, placeId)

et ainsi de suite... Je pense que la deuxième approche est meilleure, mais j'ai aussi l'impression qu'il manque quelque chose dans cette conception...

Enfin, je me demande aussi quel est le meilleur endroit pour stocker le compteur du nombre de fois où l'élément a été aimé. Je ne vois que deux possibilités :

  1. dans l'élément ( Photo/Article/Place ) table
  2. par select count().

J'espère que mon explication du problème est maintenant plus complète.

0 votes

Avez-vous envisagé le XML ?

0 votes

Les nouveaux venus peuvent envisager des bases de données de graphes comme neo4j qui est conçu exclusivement pour traiter des connexions complexes

242voto

Branko Dimitrijevic Points 28493

La solution la plus extensible est de n'avoir qu'une seule table "de base" (reliée aux "likes", aux tags et aux commentaires), et d'en "hériter" toutes les autres tables. L'ajout d'un nouveau type d'entité implique simplement l'ajout d'une nouvelle table "héritée" - elle se branche alors automatiquement sur l'ensemble de la machinerie like/tag/comment.

Le terme d'entité-relation pour cela est "catégorie" (voir la rubrique Guide des méthodes ERwin , section : " Relations entre sous-types "). Le symbole de la catégorie est :

Category

En supposant qu'un utilisateur peut aimer plusieurs entités, qu'une même balise peut être utilisée pour plusieurs entités mais qu'un commentaire est spécifique à une entité, votre modèle pourrait ressembler à ceci :

ER Diagram


En fait, il y a trois façons de mettre en œuvre la "catégorie ER" :

  • Tous les types dans un seul tableau.
  • Tous les types de béton dans des tableaux séparés.
  • Tous les types concrets et abstraits dans des tableaux séparés.

À moins que vous n'ayez des exigences de performance très strictes, la troisième approche est probablement la meilleure (c'est-à-dire que les tables physiques correspondent 1:1 aux entités du diagramme ci-dessus).

3 votes

Excellente réponse, merci. J'espère que j'arriverai à l'implémenter... et je me demande comment l'ORM de Django va s'en occuper (ou comment je vais le faire moi-même... mais, c'est l'autre problème ;) ). Mais, pouvez-vous m'expliquer, car je pense que je ne comprends pas bien - ce que vous avez dessiné pour moi (merci !) est la troisième approche que vous avez mentionnée ?

3 votes

@Kokos Essentiellement, l'approche (3) signifie que ENTITÉ est une table, PHOTO est une table, ARTICLE est une table et LIEU est une table. L'approche (2) signifierait qu'il y a pas de pour ENTITY et l'approche (1) signifierait qu'il n'y a qu'une seule table. L'existence de toutes ces approches (qui ont toutes leurs forces et leurs faiblesses) est la conséquence malheureuse du fait qu'un SGBDR typique ne supporte pas nativement l'héritage des tables.

0 votes

@Branko C'est excellent.. Une question... Je suis confus... Vous avez une table ENTITY qui est liée à toutes les photos, articles (tableaux) etc... Je dois utiliser le type de données GUID pour l'ID de l'entité PK dans ENTITY et toutes les catégories parce que, par exemple, vous pouvez avoir la photo avec l'ID 1 et le lieu avec l'ID 1 ? Ou j'ai manqué le point... tnx...

30voto

wallyk Points 33150

Puisque vous "détestez" les bases de données, pourquoi essayez-vous d'en mettre une en place ? Demandez plutôt l'aide de quelqu'un qui aime et respire ce genre de choses.

Sinon, apprenez à aimer votre base de données. Une base de données bien conçue simplifie la programmation, l'ingénierie du site, et facilite son fonctionnement continu. Même un concepteur de base de données expérimenté n'aura pas une vision complète et parfaite : certains changements de schéma seront nécessaires au fur et à mesure de l'émergence de modèles d'utilisation ou de l'évolution des besoins.

S'il s'agit d'un projet individuel, programmez l'interface de la base de données en opérations simples à l'aide de procédures stockées : add_user, update_user, add_comment, add_like, upload_photo, list_comments, etc. N'intégrez pas le schéma dans une seule ligne de code. De cette manière, le schéma de la base de données peut être modifié sans affecter le code : seules les procédures stockées doivent connaître le schéma.

Vous devrez peut-être remanier le schéma plusieurs fois. C'est normal. Ne vous souciez pas de le rendre parfait dès la première fois. Faites en sorte qu'il soit suffisamment fonctionnel pour servir de prototype à une conception initiale. Si vous avez le temps, utilisez-le un peu, puis supprimez le schéma et recommencez. C'est toujours mieux la deuxième fois.

3 votes

Parce que je dois le mettre en œuvre par moi-même. Du moins pour l'instant... et, je me suis dit que c'était peut-être une bonne occasion de commencer à aimer un peu les bases de données ;) Merci pour votre suggestion de procédure stockée. Quelqu'un sait-il si l'ORM de Django les mappe automatiquement ?

8 votes

J'adore votre dernière phrase - C'est toujours mieux la deuxième fois.

4 votes

C'est toujours mieux la deuxième fois. Yup

25voto

user964260 Points 107

Il s'agit d'une idée générale ne prêtez pas beaucoup d'attention au style des noms de champs, mais plutôt à la relation et à la structure.

enter image description here

Ce pseudo-code va obtenir tous les commentaires de la photo avec l'ID 5.
SELECT * FROM actions
WHERE actions.id_Stuff = 5
AND actions.typeStuff="photo"
AND actions.typeAction = "commentaire".

Ce pseudo-code va obtenir tous les likes ou les utilisateurs qui ont aimé la photo avec l'ID 5.
(vous pouvez utiliser count() pour obtenir le nombre de likes)

SELECT * FROM actions  
WHERE actions.id_Stuff = 5  
AND actions.typeStuff="photo"  
AND actions.typeAction = "like"

0 votes

Je pense que vous pouvez même aimer les commentaires, comme, en cliquant sur un lien "like" dans un commentaire. Cette requête obtiendra les likes d'un commentaire(action) avec l'ID 133 : SELECT * FROM actions WHERE actions.id=133 AND actions.typeStuff = "comment" AND actions.typeAction = "like"

1 votes

Je me souviendrai certainement de cette solution pour les prochaines versions de mon système :)

0 votes

J'ai 2 tables stuff stuff1 et stuff2... J'ai suivi ce diagramme mais il y a une erreur sql en utilisant ceci... stuff1, stuff2 sont deux tables indépendantes avec leurs clés primaires indépendantes, et la table action a une colonne id_stuff qui fait référence à ces deux tables stuff1, stuff2. Maintenant, par exemple, stuff1 a 5 lignes, stuff2 a 10 lignes, lorsque j'essaie d'ajouter une ligne dans la table action avec id_stuff quelque chose de moins de 5, disons '3', il exécute la requête car il existe une ligne avec id_stuff '3' à la fois dans stuff1 et stuff2, mais si j'essaie d'ajouter une ligne avec id_stuff supérieure à 5 ...(suite au commentaire suivant)

1voto

erencan Points 1866

D'après ce que je comprends, plusieurs tables sont nécessaires. Il existe une relation de type "many to many" entre elles.

  • Table qui stocke les données de l'utilisateur telles que le nom, le prénom, la date de naissance avec un champ d'identité.
  • Table qui stocke les types de données. Ces types peuvent être des photos, des partages, des liens. Chaque type doit avoir une table unique. Il existe donc une relation entre leurs tables individuelles et cette table.
  • chaque type de données différent a sa table. par exemple, les mises à jour de statut, les photos, les liens.
  • la dernière table est pour la relation many to many stockant un id, un id d'utilisateur, un type de données et un id de données.

0 votes

Si vous postez votre diagramme de base de données, je peux dessiner la relation.

1voto

djna Points 34761

Examinez les modèles d'accès dont vous aurez besoin. L'un d'entre eux semble-t-il rendu particulièrement difficile ou inefficace par un choix de conception ou un autre ?

Sinon, privilégiez celui qui nécessite le moins de tables.

Dans ce cas :

  1. Ajouter un commentaire : soit vous choisissez une table particulière many/many, soit vous insérez dans une table commune avec un identifiant spécifique connu pour ce qui est aimé, je pense que le code client sera légèrement plus simple dans votre deuxième cas.
  2. Trouver des commentaires pour l'article : ici, il semble que l'utilisation d'une table commune est légèrement plus facile - nous avons juste une seule requête paramétrée par type d'entité.
  3. Trouver les commentaires d'une personne à propos d'un type de chose : requête simple dans les deux cas
  4. Trouver tous les commentaires d'une personne à propos de toutes les choses : cela semble peu gnangnan de toute façon.

Je pense que votre approche "discriminée", l'option 2, permet d'obtenir des requêtes plus simples dans certains cas et ne semble pas beaucoup plus mauvaise dans les autres, donc je la retiendrais.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X