Je suis un développeur de logiciels. J'aime coder, mais je déteste les bases de données ... Actuellement, je crée un site Web sur lequel un utilisateur sera autorisé à marquer une entité comme aimé (comme dans FB), tag et comment comment .
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 type de chose (par exemple, des photos). Mais je dois l'activer pour 5 choses différentes (pour le moment, mais je suppose aussi que ce nombre peut augmenter, tout comme le service dans son ensemble).
J'ai trouvé des questions similaires ici, mais aucune d'entre elles n'a de réponse satisfaisante, alors je pose à nouveau cette question.
La question est de savoir comment bien efficacement et élastiquement concevoir la base de données , de sorte qu'il puisse stocker des commentaires pour différentes tables , aime pour différentes tables et balises pour elles. Certains modèles de design comme réponse seront les meilleurs;)
Description détaillée: J'ai un tableau User
avec quelques données utilisateur et 3 autres tables : Photo
avec photographies , Articles
avec articles , Places
avec places . Je souhaite autoriser tout utilisateur connecté à:
commenter l'une de ces 3 tables
marquer l'un d'eux comme aimé
taguer l'un d'eux avec un tag
Je veux aussi compter le nombre de goûts pour chaque élément et le nombre de fois où cette balise a été utilisée.
1st approche:
a) Pour les balises , je vais créer un tableau Tag [TagId, tagName, tagCounter]
, alors je vais créer plusieurs tables de relations pour: Photo_has_tags
, Place_has_tag
, Article_has_tag
.
b) Même chose pour les commentaires.
c) Je vais créer un tableau LikedPhotos [idUser, idPhoto]
, LikedArticles[idUser, idArticle]
, LikedPlace [idUser, idPlace]
. Le nombre de j'aime sera calculé par requêtes (ce qui, je suppose, est mauvais). Et...
Je n'aime vraiment pas ce dessin pour la dernière partie, ça sent mauvais pour moi;)
2dakota du Nord approche:
Je vais créer un tableau ElementType [idType, TypeName == some table name]
qui sera peuplé par l’administrateur (moi) avec les noms de tables pouvant être aimées , commenté ou étiqueté . Ensuite, je vais créer des tables :
une) LikedElement [idLike, idUser, idElementType, idLikedElement]
et identique pour les commentaires et les balises avec les colonnes appropriées pour chacun. Maintenant, quand je veux faire une photo aimé, je vais 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 je sens aussi que quelque chose manque dans cette conception aussi ...
Enfin, je me demande également quel est le meilleur endroit pour stocker le nombre de fois où l'élément a été aimé. Je ne peux penser qu'à deux manières:
Photo/Article/Place
) tableJ'espère que mon explication de la question est plus approfondie maintenant.
La solution la plus extensible consiste à n'avoir qu'une seule table "de base" (connectée à des "j'aime", des balises et des commentaires) et à "en hériter" toutes les autres tables. L'ajout d'un nouveau type d'entité implique simplement l'ajout d'un nouveau tableau "hérité" - il se connecte ensuite automatiquement à l'ensemble, comme/tag/commentaire.
Le terme entité-relation utilisé est "catégorie" (voir le Guide de méthodes ERwin , section: "Relations entre sous-types"). Le symbole de la catégorie est:
En supposant qu'un utilisateur puisse aimer plusieurs entités, une même balise peut être utilisée pour plusieurs entités mais si un commentaire est spécifique à une entité, votre modèle pourrait ressembler à ceci:
BTW, il y a environ 3 façons d'implémenter la "catégorie ER":
À moins d’exigences de performances très strictes, la troisième approche est probablement la meilleure (ce qui signifie que les tables physiques correspondent à 1: 1 aux entités du diagramme ci-dessus).
Puisque vous "détestez" les bases de données, pourquoi essayez-vous de les mettre en place? Au lieu de cela, sollicitez 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 expérimenté en d/b n'aura pas une vision complète et parfaite: certains changements de schéma seront nécessaires ultérieurement, au fur et à mesure de l'apparition de modèles d'utilisation ou de modifications des exigences.
S'il s'agit d'un projet à une personne, programmez l'interface de 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 base de données peut être modifié sans affecter le code: seules les procédures stockées doivent être renseignées sur le schéma.
Vous devrez peut-être refactoriser le schéma plusieurs fois. C'est normal. Ne vous inquiétez pas pour que tout soit parfait la première fois. Il suffit de le rendre suffisamment fonctionnel pour créer un prototype de conception initiale. Si vous avez le temps, utilisez-en un peu, supprimez le schéma et recommencez. C'est toujours mieux la deuxième fois.
C’est une idée générale, ne faites pas très attention au style des noms de champs, mais plutôt à la relation et à la structure.
Ce pseudocode obtiendra tous les commentaires de la photo portant l'ID 5
SELECT * FROM actions
WHERE actions.id_Stuff = 5
AND actions.typeStuff = "photo"
AND actions.typeAction = "comment"
Ce pseudocode obtiendra tous les goûts ou les utilisateurs qui ont aimé une 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"
pour autant que je comprends. plusieurs tables sont nécessaires. Il existe de nombreuses relations entre eux.
Regardez les modèles d'accès dont vous aurez besoin. Est-ce que l'un d'eux semble rendre particulièrement difficile ou inefficace mon choix de conception ou l'autre?
Si non privilégier celui qui nécessite le moins de tables
Dans ce cas:
Je pense que votre approche "discriminée", option 2, donne lieu à des requêtes plus simples dans certains cas et ne semble pas beaucoup pire dans les autres, alors j'y vais.
Allez certainement à la deuxième approche où vous avez une table et stockez le type d'élément pour chaque ligne, cela vous donnera beaucoup plus de flexibilité. En gros, quand on peut logiquement faire quelque chose avec moins de tables, il vaut presque toujours mieux utiliser moins de tables. Un des avantages qui me vient à l’esprit au sujet de votre cas particulier est que vous souhaitez supprimer tous les éléments appréciés d’un utilisateur donné. Dans le cadre de votre première approche, vous devez émettre une requête pour chaque type d’élément, mais avec la deuxième approche, cela peut être fait. avec une seule requête ou si vous envisagez d'ajouter un nouveau type d'élément, la première approche implique la création d'une nouvelle table pour chaque nouveau type, mais avec la deuxième approche, vous ne devez rien faire ...