database-design - para - introducción a android studio incluye proyectos reales y el código fuente pdf
Diseño de base de datos para etiquetar múltiples tipos de entidades (6)
Actualmente estoy diseñando un esquema de base de datos que se usa para almacenar recetas. En esta base de datos existen diferentes tipos de entidades que deseo poder etiquetar (ingredientes, emisores de recetas, recetas, etc.). Entonces una etiqueta tiene múltiples relaciones n: m. Si uso el "diseño de tres mesas", esto daría como resultado tablas (tabla cruzada) para cada tipo de entidad (recetas, ingredientes, emisores) que tengo. En otras palabras, cada vez que presento una entidad, debo agregar una tabla cruzada para ella.
Estaba pensando en crear una tabla que tenga una identificación única, a la que se refieran todas las entidades, y una relación: m entre la tabla de etiquetas y la tabla "id única". De esta forma, solo hay una tabla cruzada entre la tabla "id única" y la tabla de etiquetas.
En caso de que algunas personas piensen que ya se hizo esta pregunta. Ya leí Database Design for Tagging . Y allí se menciona el diseño de tres mesas.
¿Qué tal esto?
Tipos (PK: Tipo , set_id [, TypeDesc])
Atributos (PK :( set_id , FK: Type ), Value)
PD: Bold / Italics Realy Suck
Creo que estás en el camino correcto. Lo describiste muy bien, tienes un par de entidades diferentes. Puede crear una tabla llamada entidades que contenga todos los atributos comunes (si los hay). Así por ejemplo
Entidad
- EntityId
- Nombre
Ingrediente
- EntityId
- Cantidad
RecipeIssuer
- EntityId
- SomeOtherInformation
Ahora puedes tener una tabla para etiquetar entidades.
No veo nada malo en tener una sola tabla para todas las asignaciones de etiquetas (a diferencia de varias tablas, una para cada entidad etiquetable).
Sin embargo, un detalle importante en su diseño sigue siendo ambiguo para mí: si va a tener algo en esta línea
- - - - - - - - - -
Tag
ID // PK
Name
...
- - - - - - - - - -
Taggable
ID // PK
...
- - - - - - - - - -
TagAssignment
Tag_ID // FK -> Tag.ID
Taggable_ID // FK -> Taggable.ID
...
- - - - - - - - - -
EntityOne
Taggable_ID // FK -> Taggable.ID
...
- - - - - - - - - -
EntityTwo
Taggable_ID // FK -> Taggable.ID
...
entonces, ¿sus clases de entidad van a tener sus propias claves primarias o van a usar EntityOne.TaggableID
y EntityTwo.TaggableID
como claves primarias de facto para EntityOne
y EntityTwo
?
En la mayoría de los casos, sería cauteloso y dejaría que las entidades tuvieran sus propios ID:
- - - - - - - - - -
EntityOne
ID // PK
Taggable_ID // FK -> Taggable.ID (Nullable)
...
- - - - - - - - - -
EntityTwo
ID // PK
Taggable_ID // FK -> Taggable.ID (Nullable)
...
Esto no requeriría que cada entidad tenga una instancia correspondiente de Taggable
y, por lo tanto, esto no requeriría que cada parte del código involucrado con una entidad también esté al tanto de las etiquetas. Sin embargo, si el etiquetado va a ser realmente omnipresente en el sistema, y si está seguro de que no necesitará ningún otro "antepasado común" para las entidades (es decir, que no sea Taggable
), entonces puede escapar sin "intrínseco". "ID para entidades.
NB : Nunca traté de implementar algo como esto, así que todas mis recomendaciones son puramente teóricas. Entonces, por favor no me disparen si no veo algunos defectos obvios. :-)
En respuesta al comentario de Bill Karwin:
Tiene razón: el diseño descrito anteriormente no impide que varias entidades se refieran a la misma Taggable
. Pero:
Como dije, todo depende de los requisitos. Si estamos seguros de que
Taggable
será el único "antecesor común" de las entidades, entonces está bien usar lasTaggable_ID
Taggable_ID como PK para las entidades. Pero, por ejemplo, ¿qué pasa si algunas entidades que resultan ser "etiquetables" también tienen que ser "observables" (notificaciones de pensamiento, programaciones de notificaciones, etc.) o "lo que sea capaz" :-)? ¿Podemos cortar todas esas "habilidades" atando cualquier entidad aTaggable
?Si realmente quiere tener un nivel de DB que cumpla con la restricción one-taggable-one-entity ... AFAIK, hay al menos una forma común de hacerlo sin hacer que los FK sirvan como PK: al introducir "tipos" de taggables (que puede ser útil para alguna otra funcionalidad de todos modos).
Algo en esta línea nos dejaría comer un pastel y comerlo:
- - - - - - - - - -
Taggable
ID // PK
Type
...
- - - - - - - -
Constraint: (ID, Type) is unique
- - - - - - - - - -
EntityOne
ID
Taggable_ID
Taggable_Type // Constraint: always = ''EntityOne''
...
- - - - - - - -
FK: (Taggable_ID, Taggable_Type) -> (Taggable.ID, Taggable.Type)
Por supuesto, todo esto es más complicado que simplemente tener entidades vinculadas a taggables. Pero solo estaba tratando de analizar qué, en mi humilde opinión, debería considerarse, además de la imagen limitada proporcionada por la pregunta original.
Yo diría que depende de cómo quieras usar las etiquetas.
Me imagino que podrías crear una tabla de intersección adicional para cada tipo de entidad que quieras etiquetar, si solo buscas un tipo de entidad a la vez. En otras palabras, sería normal decir: "muéstreme los ingredientes con la etiqueta ''delicioso''", pero no está claro lo que significaría decir: "muéstreme los ingredientes y los emisores de recetas con la etiqueta ''delicioso''". caso, tener una mesa de intersección separada por entidad está bien.
Pero si necesita buscar todas las entidades de todos los tipos con una etiqueta determinada, entonces es más fácil usar la única tabla de "ID". Haga que todas las tablas de entidad apunten a ella con una columna que defina como clave principal y como clave externa:
CREATE TABLE Recipes (
recipe_id INT NOT NULL PRIMARY KEY, -- not auto-generated
FOREIGN KEY (recipe_id) REFERENCES Taggables(id)
);
La única debilidad de este plan es que no puede evitar que una fila en Recipes
e Ingredients
apunte a la misma fila en Taggables
.
INSERT INTO Taggables (id) VALUES (327);
INSERT INTO Recipes (recipe_id, name) VALUES (327, ''Hollandaise sauce'');
INSERT INTO Ingredients (ingr_id, name) VALUES (327, ''eggs'');
¿Desea que todas las etiquetas asociadas con huevos se apliquen también a la salsa holandesa?
Solo estoy señalando este aspecto del diseño de una sola mesa. Todavía puede ser la mejor manera de modelar su etiquetado, dados otros requisitos. Pero debe estar atento al potencial de colisión de los identificadores en las tablas dependientes.
hacer tablas como normales para recetas, ingredientes, etc.
entonces su tabla de etiquetas debería verse así: Id, Type, Tag
Recomiendo usar una enumeración en el código para distinguir los diferentes "Tipos" (entidades).
También tengo un "problema" similar en mis manos. Estoy desarrollando una pequeña base de datos de productos que implica el etiquetado y también le da un valor a las etiquetas (nombre de la etiqueta: color, valor: verde, por ejemplo).
Las dos tablas principales son artículos (I) y artículos (A). Los artículos son artículos físicos reales, y los artículos no tienen artículos. Los artículos son algo que se puede mostrar en un sitio web y los artículos son los que se almacenan en un almacén. Un pequeño ejemplo de esta relación podría ser piezas de automóvil. Un radiador con dimensiones conocidas y otros datos en realidad puede adaptarse a muchos modelos y marcas diferentes, es por eso que el elemento utilizado para representar el radiador se refiere a varios artículos que indican lo que el radiador puede caber. Por otro lado, podríamos tener dos radiadores diferentes disponibles para un modelo, uno que sea una versión nueva de fábrica y otro que esté recién remanufacturado. En tal caso, hay dos elementos relacionados con el mismo artículo.
Entonces, I y A tienen una relación N: M.
Los artículos y artículos tienen ciertas propiedades. Por ejemplo, el artículo del radiador puede tener datos como condición, material, peso, altura, ancho y espesor. El artículo también contiene información básica como marca, modelo, año, motor, etc., pero también podría necesitar algunos datos especiales, como el modelo del chasis, el tipo de transmisión o alguna otra cosa, como dos tipos diferentes de accesorios que se hayan utilizado en el mismo modelo. Debido a que dos elementos pueden enlazar a un artículo, significa que no puedo etiquetar artículos. Etiquetar un artículo con ambos valores de condición es simplemente estúpido, por otro lado etiquetar un elemento con múltiples instancias de un modelo, marca o algún requisito especial tampoco es una buena idea. Hay dos tipos de propiedades, la primera indica cómo es y el segundo tipo indica qué encajará.
Las etiquetas no tienen que tener un valor, simplemente pueden actuar como una etiqueta convencional que se asigna a una entidad.
Los radiadores son solo un ejemplo de un producto simple. También podríamos poner algunas partes de la computadora o ropa en nuestra base de datos. Esto significa que necesito poder poner diferentes ''etiquetas'' en dos entidades diferentes, I y A.
Necesito poder implementar una búsqueda de artículos en una tienda en línea. Digamos que estoy usando una navegación basada en árboles donde tengo una categoría llamada "radiadores nissan usados". La búsqueda implicaría buscar tanto los artículos como los artículos, los artículos tienen la etiqueta Modelo: Nissan, y los artículos tienen la etiqueta Condición: Usado. Por supuesto, cuando el usuario mira el artículo, verá todos los elementos asociados con el artículo.
Una de las soluciones con las que estoy reflexionando es el diseño de una base de datos triangular donde hay una tabla común llamada etiquetas para todas las propiedades y etiquetas.
Tenemos los ítems de tablas (I), artículos (A) y etiquetas (T). Se unen a las relaciones N: M: I2A une los artículos a los artículos. T2I une las etiquetas a los elementos y también puede almacenar el valor de la etiqueta o propiedad. T2A une las etiquetas a los artículos y también puede almacenar un valor para la etiqueta.
En papel, este diseño de 6 mesas para abordar este problema se ve bastante bien, pero me está dando dolor de cabeza la forma de hacer una consulta decente donde puedo seleccionar los artículos que coinciden con un conjunto de etiquetas diferentes y sus valores, por ejemplo: Condition = Remanufactured , Marca = Nissan
Lo que quiero poder hacer es algo como www.summitracing.com. Seleccione Departamentos de la izquierda debajo de "Comprar", seleccione cualquier categoría y verá cómo han logrado darle algunas propiedades a los elementos. Tienen el tamaño del motor para la mayoría de las aplicaciones, pero cuando buscan llantas, también tienen una propiedad para el ancho.
Cualquier comentario sobre esto sería muy apreciado, estoy empezando a golpear a los muertos tratando de diseñar esto.