2010-11-26 21 views
7

Estoy tratando de imitar algo similar a FB. Básicamente, los usuarios pueden publicar comentarios en varias partes del perfil de un usuario (por ejemplo, "muro", "foto", etc.). Creo que el siguiente modelo funcionará:Modelado de base de datos: Facebook me gusta mensajes

=========================== 
wall_message 
=========================== 
- id (PK) 
- parent_id (FK) 
- wall_owner_profile_id (FK, identify whose wall the message is for) 
- poster_profile_id (FK) 
- message 
- timestamp 

=========================== 
media_message 
=========================== 
- id (PK) 
- parent_id (FK) 
- media_id (FK, identify which photo, video, etc.) 
- poster_profile_id (FK) 
- message 
- timestamp 

parent_id permite que los mensajes sean "agrupados" en una discusión relacionada. El primer mensaje parent_id será 0 y los mensajes subsiguientes tendrán PK como el valor parent_id (creando una relación padre-hijo).

poster_profile_id identifica quién ha publicado el mensaje.

Las dos tablas anteriores son muy similares. ¿Sería una buena idea para combinarlos, tales como:

=========================== 
message 
=========================== 
- id (PK) 
- parent_id (FK) 
- type (ENUM: "wall", "media", etc.) 
- types_id (FK, see explanation below) 
- poster_profile_id (FK) 
- message 
- timestamp 

En este caso, si, por ejemplo, type es "pared", entonces types_id es igual a "wall_owner_profile_id" de la primera tabla. Si, por ejemplo, type es "media", entonces types_id es igual a la segunda tabla media_id.

Estoy un poco preocupado de que el segundo enfoque requiera una columna para explicar el significado de otra columna. Una desventaja de esto, supongo, es que no habría integridad referencial para types_id (a diferencia de "wall_owner_profile_id" y "media_id").

¿Cuál sería la mejor manera de abordar este problema?

EDIT 1:

parece que esta es la solución hasta el momento:

=========================== 
message 
=========================== 
- message_id (PK) 
- parent_message_id (FK) 
- profile_id (FK, referring to who posted the message) 
- message 
- subject (applicable only for emails) 
- timestamp 

=========================== 
wall_message 
=========================== 
- message_id (FK) 
- profile_id (FK, referring to who received the message/owner of wall) 

=========================== 
media_message 
=========================== 
- message_id (FK) 
- media_id (FK) 

=========================== 
email_message 
=========================== 
- message_id (FK) 
- profile_id (FK, referring to who received the message) 
+1

¿Ha revisado el nuevo modelo de datos? – PerformanceDBA

Respuesta

3

En primer lugar, algunas respuestas a puntos pequeños, para mantenerlo en la ruta recta y estrecha de las bases de datos relacionales y el diseño db.

  1. Toda idea es colocar como muchas de las reglas justo en la base de datos, en un solo lugar, y no en el código. Casi todo se puede hacer a través de restricciones DDL: FK; CHECK restricciones; y RULES (todos los requisitos de SQL ISO/IEC/ANSI). Entonces todos los usuarios (su aplicación es un usuario) pueden ver todas las reglas y comprender mejor la base de datos. Eso protege el DB, sin importar qué cliente se use para ejecutar el código. Los proveedores de Db (eso significa la implementación comercial, no gratuita) de estas restricciones son más confiables que el código.

  2. El requisito (no convencional) para insertar filas en una tabla secundaria es que la fila principal debe existir primero. Eso es lo que hace la restricción FK, asegura que la fila padre existe. En una tabla de muchos a muchos, ambas filas primarias deben existir antes de que se pueda insertar el elemento secundario (con dos FK, una para cada elemento primario).

  3. types_id es una idea horrible porque tiene reglas de diseño rotas y quitó la posibilidad de RI. Mejor tener columnas separadas con RI (restricciones FK para cada padre). (Pero hay una forma aún mejor).

  4. Todas sus columnas Id, las PK, deben cambiarse de nombre TableId. Cada uno debe tener Private DataType del mismo nombre. El nombre de la columna se usa sin cambios donde sea que exista, como un FK. La única excepción es cuando tiene dos FK en la misma tabla principal: allí debe ser RoleTableId.

¿Cuál sería la mejor manera de abordar este problema?

Normalizar. Y tendrá problemas que están expuestos, que debe resolver. Por lo tanto, normaliza de nuevo. Y sigue haciéndolo hasta que no tengas problemas que resolver.

  1. Su tabla de mensajes individuales ya está a medio camino allí. Has normalizado intuitivamente las dos tablas en una. Pero hay problemas que resolver, así que manejémoslos.

    • Sebastian ha proporcionado las dos tablas de muchos a muchos, por lo que no voy a repetir.
      .
  2. Antes de decidir que eso es definitivo (y por lo tanto las dos mesas-muchos-a-muchos son finales), sugiero a normalizar Wall y Media. Para mí, parece que hay muchas columnas comunes. Si lo normalizas, obtendrás una tabla. Como se trata de una cosa expuesta o proporcionada por un Person con el propósito de invitar a Messages, y el tipo puede ser { Photo | Album | Mailbox | Wall }, lo llamaría PersonFurniture o PersonObject.

    • Si eso termina como una sola tabla, entonces no necesitará dos tablas de muchas a muchas, solo una.

respuestas a los comentarios

  1. Es más fácil y más rápido para dibujar el modelo, que para escribir largas discusiones. He pensado en la mayoría de tus preguntas. Por favor verifique esto y haga preguntas específicas sobre cualquier cosa que no entienda.

Link to Social Network Data Model (Página 3)

Link to IDEF1X Notation para aquellos que no están familiarizados con el estándar de modelado relacional.

  • elegir sus propios nombres de tabla y columna
  • Message.Subject se puede configurar para CHAR(0) o ignorado, si no es por correo electrónico.
  • que wall_message y email_message son idénticas es no un problema, los he normalizado en una tabla
  • si se trata de un wall_message o email_message o media_message es una cuestión de donde es "enviado", ¿verdad? Puede rechazar fácilmente cualquier función (por ejemplo, agrupación) para cualquier tipo de mensaje a través de una restricción CHECK.
  • usted no ha respondido (2) arriba
  • Creo que la agrupación de mensajes es diferente de la agrupación de medios: piense en cuándo un álbum de fotos tiene una lista de mensajes en él.
  • nada es un problema, toda la idea de modelado es, el papel es barato; la idea general de los db relacionales es hacer todo lo posible mediante restricciones, controles y reglas. Si algo está mal, podemos cambiarlo.

(¿Quieres Raza (3 niveles) o 2 niveles en su pregunta Raza?)

+0

ver mi "Editar 1". He incorporado cambios basados ​​en mi comprensión de las sugerencias aquí hasta ahora. No estoy seguro de cómo puedo normalizar aún más 'Wall' y' Media'. Ellos parecen normalizados para mí. – StackOverflowNewbie

+0

también, tres preguntas: 1.) ¿Hay algún problema con message-> subject (dado que solo se aplica a correos electrónicos)? 2.) 'wall_message' y' email_message' son idénticos; ¿es esto un problema? 3.) Solo 'wall_message' y' email_message' tienen este concepto de "agrupación" (y por lo tanto necesitan parent_message_id); media_message lo necesita ya que está agrupado por media_id. ¿Hay algún problema con esto? – StackOverflowNewbie

+1

@SONewbie. Respondido en mi post. – PerformanceDBA

1

que podría tener su mensaje de mesa, y luego n: tablas de relación m, es decir

message_to_wall: 
- messageID 
- wallID 

message_to_media: 
- messageID 
- mediaID 

De esta manera conservas la integridad referencial y solo tienes una tabla de mensajes.

Esto, por supuesto, técnicamente permitiría tener un mensaje publicado en una pared Y a un elemento multimedia (foto, etc.). Entonces no puedes restringir esto fácilmente.

De lo contrario, si realmente no necesita una base de datos relacional, podría pensar en utilizar una base de datos NoSQL como CouchDB o MongoDB. Puede almacenar todos esos comentarios directamente en la pared o en el documento multimedia. De esta forma, no tienes todas las consultas requeridas para unir y los comentarios están todos vinculados a los medios o al muro.

+0

@Sebastian: estoy usando MySQL. Dado que ambas tablas podrían tener el mismo 'messageId', ¿ve algún problema potencial con su diseño? Estoy bastante seguro de que puedo evitar que esto suceda a través del código, pero tengo curiosidad si hay un problema desde una perspectiva DB. – StackOverflowNewbie

+0

... y ¿cómo podría usar el mismo diseño básico para admitir mensajes de correo electrónico entre usuarios? – StackOverflowNewbie

+0

No debería haber ningún problema desde la perspectiva DB. Debería intentar evitar que esto suceda utilizando su Código, sí. Con respecto a los mensajes de correo electrónico, puede crear otra tabla de relaciones message_to_user, en la que puede asignar mensajes a los usuarios (especificando el destinatario). –

Cuestiones relacionadas