Soy un desarrollador de software. Me encanta codificar, pero odio las bases de datos ... Actualmente, estoy creando un sitio web en el que un usuario podrá marcar una entidad como me gusta (como en FB), etiquetarla y comentar .
Me atasco en el diseño de tablas de bases de datos para manejar esta funcionalidad. La solución es trivial, si podemos hacer esto solo para un tipo de cosas (por ejemplo, fotos). Pero necesito habilitar esto para 5 cosas diferentes (por ahora, pero también asumo que este número puede crecer, a medida que crece todo el servicio).
Encontré algunas preguntas similares aquí, pero ninguna de ellas tiene una respuesta satisfactoria, por lo que estoy haciendo esta pregunta nuevamente.
La pregunta es cómo diseñar la base de datos de manera adecuada, eficiente y elástica , de modo que pueda almacenar comentarios para diferentes tablas , me gusta para diferentes tablas y etiquetas para ellos. Algún patrón de diseño como respuesta será mejor;)
Descripción detallada : Tengo una tabla User
con algunos datos de usuario, y 3 tablas más : Photo
con fotografías , Articles
con artículos , Places
con lugares . Quiero habilitar a cualquier usuario registrado para:
comentar cualquiera de esas 3 tablas
marcar cualquiera de ellos como gustado
etiquetar cualquiera de ellos con alguna etiqueta
También quiero contar la cantidad de Me gusta para cada elemento y la cantidad de veces que se usó esa etiqueta en particular.
1 st enfoque :
a) Para las etiquetas , voy a crear una tabla Tag [TagId, tagName, tagCounter]
, a continuación, voy a crear muchos-a-muchos relaciones mesas para: Photo_has_tags
, Place_has_tag
, Article_has_tag
.
b) Lo mismo cuenta para los comentarios.
c) Voy a crear una tabla LikedPhotos [idUser, idPhoto]
, LikedArticles[idUser, idArticle]
, LikedPlace [idUser, idPlace]
. El número de Me gusta se calculará mediante consultas (lo cual, supongo que es malo). Y...
Realmente no me gusta este diseño para la última parte, me huele mal;)
2 nd enfoque :
Crearé una tabla ElementType [idType, TypeName == some table name]
que será rellenada por el administrador (yo) con los nombres de las tablas que pueden gustarse , comentarse o etiquetarse . Entonces crearé tablas :
a) LikedElement [idLike, idUser, idElementType, idLikedElement]
y lo mismo para Comentarios y Etiquetas con las columnas apropiadas para cada uno. Ahora, cuando quiera hacer una foto que me guste, insertaré:
typeId = SELECT id FROM ElementType WHERE TypeName == 'Photo'
INSERT (user id, typeId, photoId)
y para lugares:
typeId = SELECT id FROM ElementType WHERE TypeName == 'Place'
INSERT (user id, typeId, placeId)
y así sucesivamente ... Creo que el segundo enfoque es mejor, pero también siento que falta algo en este diseño también ...
Por último, también me pregunto cuál es el mejor lugar para almacenar el mostrador por cuántas veces le gustó el elemento. Solo puedo pensar en dos formas:
- en la
Photo/Article/Place
tabla element ( ) - por cuenta selecta ().
Espero que mi explicación del problema sea más exhaustiva ahora.
Respuestas:
La solución más extensible es tener una sola tabla "base" (conectada a "me gusta", etiquetas y comentarios) y "heredar" todas las demás tablas de ella. Agregar un nuevo tipo de entidad implica simplemente agregar una nueva tabla "heredada"; luego se conecta automáticamente a toda la maquinaria de me gusta / etiqueta / comentario.
El término entidad-relación para esto es "categoría" (consulte la Guía de métodos de ERwin , sección: "Relaciones de subtipo"). El símbolo de categoría es:
Suponiendo que a un usuario le gusten varias entidades, se puede usar una misma etiqueta para más de una entidad pero un comentario es específico de la entidad, su modelo podría verse así:
Por cierto, hay aproximadamente 3 formas de implementar la "categoría ER":
A menos que tenga requisitos de rendimiento muy estrictos, el tercer enfoque es probablemente el mejor (lo que significa que las tablas físicas coinciden 1: 1 con las entidades en el diagrama anterior).
fuente
BIGINT
9223372036854775807. Suponiendo que inserte una fila cada segundo, se quedará sin valores disponibles en ~ 300 mil millones de años. ¡Seguramente, para entonces, podrá transferir a enteros de 128 bits!Ya que "odias" las bases de datos, ¿por qué estás tratando de implementar una? En cambio, solicite ayuda de alguien que ama y respira estas cosas.
De lo contrario, aprende a amar tu base de datos. Una base de datos bien diseñada simplifica la programación, diseña el sitio y suaviza su operación continua. Incluso un diseñador experimentado de d / b no tendrá una previsión completa y perfecta: se necesitarán algunos cambios de esquema en el futuro a medida que surjan patrones de uso o cambien los requisitos.
Si se trata de un proyecto individual, programe la interfaz de la base de datos en operaciones simples utilizando procedimientos almacenados: add_user, update_user, add_comment, add_like, upload_photo, list_comments, etc. No incruste el esquema en una sola línea de código. De esta manera, el esquema de la base de datos se puede cambiar sin afectar ningún código: solo los procedimientos almacenados deben conocer el esquema.
Puede que tenga que refactorizar el esquema varias veces. Esto es normal. No te preocupes por hacerlo perfecto la primera vez. Simplemente hágalo lo suficientemente funcional como para crear un prototipo de diseño inicial. Si tiene el lujo del tiempo, úselo y luego elimine el esquema y vuelva a hacerlo. Siempre es mejor la segunda vez.
fuente
Esta es una idea general, no preste mucha atención al estilo de los nombres de campo, sino más a la relación y estructura
Este pseudocódigo obtendrá todos los comentarios de la foto con ID 5
SELECT * FROM actions
WHERE actions.id_Stuff = 5
AND actions.typeStuff = "photo"
AND actions.typeAction = "comment"
Este pseudocódigo obtendrá todos los me gusta o usuarios a quienes les gustó la foto con ID 5
(puede usar count () para obtener la cantidad de me gusta)
fuente
SELECT * FROM actions WHERE actions.id=133 AND actions.typeStuff = "comment" AND actions.typeAction = "like"
id_stuff
columna valores únicos en cada una de las tres tablas?hasta donde yo entiendo. Se requieren varias mesas. Hay una relación de muchos a muchos entre ellos.
fuente
Mira los patrones de acceso que vas a necesitar. ¿Alguno de ellos parece hacer particularmente difícil o ineficiente mi elección de diseño u otra?
Si no favorece el que requiere menos tablas
En este caso:
Creo que su enfoque "discriminado", opción 2, produce consultas más simples en algunos casos y no parece mucho peor en los demás, por lo que seguiría con eso.
fuente
Definitivamente vaya con el segundo enfoque donde tiene una tabla y almacene el tipo de elemento para cada fila, le dará mucha más flexibilidad. Básicamente, cuando algo se puede hacer lógicamente con menos tablas, casi siempre es mejor ir con menos tablas. Una ventaja que me viene a la mente ahora sobre su caso particular, considere que desea eliminar todos los elementos que le gustan a un determinado usuario, con su primer enfoque, debe emitir una consulta para cada tipo de elemento, pero con el segundo enfoque puede hacerse con solo una consulta o considerar cuándo desea agregar un nuevo tipo de elemento, con el primer enfoque implica crear una nueva tabla para cada nuevo tipo, pero con el segundo enfoque no debe hacer nada ...
fuente
Considere usar la tabla por entidad para comentarios, etc. Más tablas: mejor fragmentación y escalado. No es un problema controlar muchas tablas similares para todos los marcos que conozco.
Algún día necesitarás optimizar las lecturas de dicha estructura. Puede crear fácilmente tablas agravantes sobre las básicas y perder un poco en las escrituras.
Una mesa grande con diccionario puede volverse incontrolable algún día.
fuente