Dans un clone StackOverflow, quelle relation doit une table de commentaires ont aux questions et réponses?

StackOverflow https://stackoverflow.com/questions/987654

Question

Dans une application similaire à Stackoverflow que je construis, je suis en train de décider quelle relation mes Questions, tables Answers et Comments devraient avoir.

Je pourrais avoir Questions et Answers tous deux être représentés par un Posts de table unique.

Cela permettrait Comments d'avoir une clé étrangère à Posts.

Mais si Questions et Answers sont des tables séparées, quelles relations devraient Comments avoir à chacun de ces?

MISE À JOUR: Bien que la réponse choisie recommande une approche héritage de table de classe et cela semble être la meilleure approche en termes de base de données, cette option est prise en charge par les rails ORM. Ainsi, dans Rails mes modèles devront utiliser l'authentification unique Héritage de Table et regardera probablement comme ceci:

class Post < ActiveRecord::Base  
end  

class Question < Post  
  has_many :answers, :foreign_key => :parent_id  
  has_many :comments, :foreign_key => :parent_id  
end  

class Answer < Post  
  belongs_to :question, :foreign_key => :parent_id  
  has_many :comments, :foreign_key => :parent_id  
end  

class Comment < Post  
  belongs_to :question, :foreign_key => :parent_id  
  belongs_to :answer, :foreign_key => :parent_id  
end


class CreatePosts < ActiveRecord::Migration  
    def self.up  
      create_table :posts do |t|  
        t.string :type 
        t.string :author   
        t.text :content  
        t.integer :parent_id   
        t.timestamps  
      end  
    end  


    def self.down  
      drop_table :posts  
    end  
end
CREATE TABLE "posts" (
  "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,  
  "type" varchar(255),  
  "author" varchar(255),  
  "content" text,  
  "parent_id" integer,  
  "created_at" datetime, 
  "updated_at" datetime
  );
Était-ce utile?

La solution

Je vais à l'approche Messages. Ceci est la meilleure façon d'assurer l'intégrité référentielle.

Si vous avez besoin des colonnes supplémentaires pour les réponses et questions, respectivement, les mettre dans des tableaux supplémentaires avec une à une relation avec les messages.

Par exemple, dans la syntaxe MySQL:

CREATE TABLE Posts (
  post_id     SERIAL PRIMARY KEY,
  post_type   CHAR(1),              -- must be 'Q' or 'A'
  -- other columns common to both types of Post
  UNIQUE KEY (post_id, post_type) -- to support foreign keys
) ENGINE=InnoDB;

CREATE TABLE Comments (
  comment_id  SERIAL PRIMARY KEY, 
  post_id     BIGINT UNSIGNED NOT NULL,
  -- other columns for comments (e.g. date, who, text)
  FOREIGN KEY (post_id) REFERENCES Posts(post_id)
) ENGINE=InnoDB; 

CREATE TABLE Questions (
  post_id     BIGINT UNSIGNED PRIMARY KEY,
  post_type   CHAR(1),              -- must be 'Q'
  -- other columns specific to Questions
  FOREIGN KEY (post_id, post_type) REFERENCES Posts(post_id, post_type)
) ENGINE=InnoDB;

CREATE TABLE Answers (
  post_id     BIGINT UNSIGNED PRIMARY KEY,
  post_type   CHAR(1),              -- must be 'A'
  question_id BIGINT UNSIGNED NOT NULL,
  -- other columns specific to Answers
  FOREIGN KEY (post_id, post_type) REFERENCES Posts(post_id, post_type)
  FOREIGN KEY (question_id) REFERENCES Questions(post_id)
) ENGINE=InnoDB;

est appelée classe Héritage de Table. Il y a une belle vue d'ensemble de l'héritage de modélisation avec SQL dans cet article: « héritage dans les bases de données relationnelles ".

Il peut être utile d'utiliser post_type si un poste donné ne peut être qu'une réponse ou une question. Vous ne voulez pas à la fois une réponse et une question pour faire référence à une donnée Post. C'est donc le but de la colonne de post_type ci-dessus. Vous pouvez utiliser des contraintes CHECK pour faire respecter les valeurs post_type, ou bien utiliser un déclencheur si votre base de données ne supporte pas les contraintes CHECK.

J'ai aussi fait une présentation qui peut vous aider. Les lames sont en http://www.slideshare.net/billkarwin/sql- -grève les anti back . Vous devriez lire les sections sur les associations polymorphes et des entités-attributs-valeur.


Si vous utilisez unique Héritage de Table, comme vous avez dit que vous utilisez Ruby on Rails, le SQL DDL ressemblerait à ceci:

CREATE TABLE Posts (
  post_id     SERIAL PRIMARY KEY,
  post_type   CHAR(1),              -- must be 'Q' or 'A'
  -- other columns for both types of Post
  -- Question-specific columns are NULL for Answers, and vice versa.
) ENGINE=InnoDB;

CREATE TABLE Comments (
  comment_id  SERIAL PRIMARY KEY, 
  post_id     BIGINT UNSIGNED NOT NULL,
  -- other columns for comments (e.g. date, who, text)
  FOREIGN KEY (post_id) REFERENCES Posts(post_id)
) ENGINE=InnoDB; 

Vous pouvez utiliser une contrainte de clé étrangère dans cet exemple, et je vous recommande de le faire! : -)

philosophie Rails tend à favoriser la mise application du modèle de données dans la couche d'application. Mais sans les contraintes d'intégrité à l'application dans la base de données, vous avez le risque que des bugs dans votre application, ou des requêtes ad hoc à partir d'un outil de recherche, peuvent nuire à l'intégrité des données.

Autres conseils

Dans les réseaux sociaux que je construis, je fais quelque chose d'un peu différent. Si vous pensez à ce sujet un commentaire pourrait être rattaché à peu près toute entité d'un site. Cela pourrait être un blog, un fil de forum ou après, un article, someones image, d'une personne de profil, un fournisseur d'un service, etc. Pour cette raison, je crée une table SystemObjects qui contient le type d'objet (référence de table). Pour la plupart, je crée des documents pour les entités de mon système qui acceptera les commentaires ... mais ceux-ci renvoient directement à mes tableaux. La table SystemObjects abrite le SystemObjectID, et un nom convivial pour référence future (une table de consultation).

Avec cela en place, je puis créer une table de commentaires qui a la référence SystemObjectID me dire quelle table pour aller chercher. Puis j'abritera également la SystemObjectRecordID qui me dit que PK de la table référencée Je suis intéressé (avec toutes les données de commentaire standard).

J'utilise cette notion de la table Systemobject pour beaucoup d'autres concepts génériques loin dans mes atteindre les sites. Pensez à Tags, évaluations, commentaires et tout autre fruit ballants qui pourrait être fixé sur votre site et agrégées pour une utilisation rapide.

En savoir plus à ce sujet dans mon livre ASP.NET 3.5 Réseaux sociaux .

Vous pouvez créer une seule table de commentaires avec deux clés étrangères, un à questions.questionID et l'autre à answers.answerId

Vous auriez besoin de deux tables de domaine qui apportent les relations ensemble CommentsForQuestions et CommentsForAnswers. Fondamentalement, vous allez avoir besoin de créer 5 tables à cet effet:

Questions
Answers
Comments
CommentsForQuestions (relates comments to questions)
CommentsForAnswers (relates comments to answers)

Le seul problème a ce que c'est inférieur à l'idée de messages parce que l'intégrité référentielle est pas aussi forte. Je peux garuntee que CommentsForQuestions se connecte à un commentaire et une question, mais je ne peux pas empêcher à la fois une question et une réponse de se connecter au même commentaire.

Une relation de clé étrangère; vous pouvez avoir QuestionComments et AnswerComments, ou vous pouvez avoir des commentaires ont une colonne de clé étrangère pour les questions et réponses (et ont ces colonnes être exclusive).

Personnellement, je partirais avec l'approche messages.

Edit: En contrepartie, il y a une troisième approche qui pourrait fonctionner; vous pourriez avoir une table de commentaires, et alors juste une table d'association qui associe les commentaires soit avec une question ou une réponse (si les commentaires auraient un ID et le commentaire, la table de jointure aurait un CommentID, un AnswerID et un QuestionID ). Ou bien, vous pourriez avoir juste une table de commentaires, ont alors une table d'association Réponse- Commentaire et une table distincte d'association Question-Commentaire.

Il y a 2 façons que je peux penser.

Tout d'abord, utilisez une autre colonne dans la table de commentaires pour indiquer si le commentaire appartient à la question ou réponse. Ainsi, le PK de la table devient Commentaire wher PostID est la clé étrangère à la question ou la réponse et PostType peut être someting comme 1 = 2 = Question et réponse.

En second lieu, utiliser une table de relation pour chaque question et réponse. Donc, vous avez une question, réponse, Commentaire, QuestionComment, et une table AnswerComment.

Disons que la clé primaire de la question, réponse, tables de commentaires sont QuestionID, AnswerID et CommentID respectivement. Ensuite, les colonnes de QuestionComment seraient [QuestionID, CommentID]. De même, les colonnes de AnswerComment seraient [AnswerID, CommentID].

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top