En un clon Stackoverflow, ¿qué relación debe tener una mesa de comentarios a las preguntas y respuestas?

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

Pregunta

En una aplicación similar a Stackoverflow que estoy construyendo, estoy tratando de decidir qué relación mis Questions, mesas y Answers Comments deben tener.

Podría tener Questions y Answers tanto ser representados por un solo Posts mesa.

Esto permitiría Comments tener una sola clave externa a Posts.

Pero si Questions y Answers tablas separadas, lo que las relaciones deben Comments tiene a cada uno de estos?

ACTUALIZACIÓN: A pesar de la respuesta elegida recomienda un enfoque Herencia de tablas de clase y esto parece el mejor enfoque en términos de bases de datos, esta opción no está soportado por los carriles de ORM. Así, en los carriles mis modelos tendrán que utilizar una sola mesa de herencia y es probable que este aspecto:

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
  );
¿Fue útil?

Solución

Me gustaría ir con el enfoque de Mensajes. Esta es la mejor manera de asegurar la integridad referencial.

Si necesita columnas adicionales para preguntas y respuestas, respectivamente, ponerlas en mesas adicionales con una relación uno-a-uno con los mensajes.

Por ejemplo, en la sintaxis de 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;

Esto se llama Clase herencia de tabla. Hay una buena visión general de la herencia de modelado con SQL en este artículo: " Herencia en bases de datos relacionales ".

Puede ser útil usar post_type por lo que un determinado mensaje puede ser sólo una respuesta o una pregunta. Usted no quiere tanto una respuesta y una pregunta para hacer referencia a un determinado mensaje. Así que este es el propósito de la columna de post_type anteriormente. Puede utilizar restricciones CHECK para hacer cumplir los valores en post_type, o bien utilizar un disparador si su base de datos no admite restricciones CHECK.

También hice una presentación que pueden ayudarle. Las diapositivas son hasta en http://www.slideshare.net/billkarwin/sql- antipatrones-strike-back. Usted debe leer las secciones sobre asociaciones polimórficas y Entidad-Atributo-Valor.


Si utiliza una sola mesa de sucesiones, como usted ha dicho que está usando Ruby on Rails, a continuación, el DDL de SQL sería el siguiente:

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; 

Se puede utilizar una restricción de clave externa en este ejemplo, y recomiendo que lo haga! : -)

filosofía

Rieles tiende a favorecer a poner la aplicación del modelo de datos en la capa de aplicación. Pero sin limitaciones en la aplicación de la integridad de la base de datos, tiene el riesgo de que los errores en su aplicación, o consultas ad hoc de una herramienta de consulta, pueden dañar la integridad de datos.

Otros consejos

En las redes sociales que construyo hago algo un poco diferente. Si se piensa en ello un comentario se podría unir a casi cualquier entidad de un sitio. Esto podría ser un blog, un hilo del foro o enviados, un artículo, de alguien imagen, de una persona de perfil, un proveedor de un servicio, etc. Por esta razón creo una tabla SystemObjects que mantiene el tipo de objeto (referencia de tabla). En su mayor parte se crea registros de las Entidades de mi sistema que aceptarán comentarios ... pero estos se asignan directamente a mis mesas. La tabla SystemObjects alberga el SystemObjectID, y un nombre descriptivo para referencia futura (una tabla de consulta).

Con esto en lugar que a continuación, crear una mesa de Comentarios que tiene la referencia SystemObjectID a decirme lo mesa para ir a buscar. Entonces yo también albergo la SystemObjectRecordID que me dice lo que PK de la tabla referenciada Me interesa (junto con todo el comentario de datos estándar).

Yo uso esta noción de la tabla Systemobject para muchos otros conceptos genéricos de largo alcance en mis sitios. Piense en las etiquetas, valoraciones, comentarios, y cualquier otra fruta que cuelga que podrían estar unido a través de su sitio y agregados para el uso rápido.

Leer más sobre esto en mi libro ASP.NET 3.5 Redes sociales .

Se puede crear una sola tabla comentarios con dos claves externas, uno a questions.questionID y el otro a answers.answerId

Se necesitaría dos mesas de dominio que traen las relaciones entre sí y CommentsForQuestions CommentsForAnswers. Básicamente, usted va a necesitar para crear 5 mesas para este propósito:

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

El único problema que esto tiene es que es inferior a la idea porque los mensajes de integridad referencial no es tan fuerte. Puedo garuntee que CommentsForQuestions se conecta a un comentario y una pregunta, pero no puedo evitar tanto una pregunta y una respuesta de la conexión a la misma observación.

Una relación de clave externa; usted puede tener QuestionComments y AnswerComments, o puede tener Comentarios tienen una columna de clave externa para ambas preguntas y respuestas (y tienen por qué ser excluyentes esas columnas).

En lo personal, me gustaría ir con el enfoque de los mensajes.

Editar: En consideración, hay un tercer enfoque que podría funcionar; es posible que tenga una mesa de comentarios, y luego sólo hay una tabla de asociación que asocia los comentarios ya sea con una pregunta o una respuesta (por lo Comentarios tendrían un ID y el comentario, la tabla de unión tendría un CommentID, un AnswerID, y una IdPregunta ). O bien, puede tener sólo una mesa de comentarios, y luego tener una tabla de asociación respuesta-comentario, y una mesa de Pregunta-comentario asociación independiente.

Hay 2 maneras en que puedo imaginar.

En primer lugar, utilizar otra columna de la tabla comentario para indicar si el comentario pertenece a la pregunta o respuesta. Por lo que el PK de la mesa se convierte en comentario RCEst PostID es la clave externa a la pregunta o la respuesta y puede ser PostType calle detrás como 1 = Pregunta y respuesta = 2.

En segundo lugar, utilizar una tabla de relación para cada pregunta y respuesta. Por lo que tiene una pregunta, respuesta, comentario, QuestionComment, y mesa AnswerComment.

Digamos que la clave primaria de pregunta, respuesta, mesas comentario a IdPregunta, AnswerID y CommentID respectivamente. A continuación, las columnas de QuestionComment serían [IdPregunta, CommentID]. Del mismo modo, las columnas de AnswerComment serían [AnswerID, CommentID].

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top