Esta pregunta es sobre cómo debería diseñar una base de datos, pueden ser bases de datos relacionales / nosql, dependiendo de cuál será la mejor solución
Dado un requisito en el que deberá crear un sistema que incluya una base de datos para rastrear "Compañía" y "Usuario". Un solo usuario siempre pertenece a una sola empresa.
- Un usuario solo puede pertenecer a una empresa
- Una empresa puede tener muchos usuarios
El diseño de la tabla "Empresa" es bastante sencillo. La empresa tendrá los siguientes atributos / columnas: (hagámoslo simple)
ID, COMPANY_NAME, CREATED_ON
Primer escenario
Simple y directo, todos los usuarios tienen el mismo atributo, por lo que esto se puede hacer fácilmente en estilo relacional, tabla de usuario:
ID, COMPANY_ID, FIRST_NAME, LAST_NAME, EMAIL, CREATED_ON
Segundo escenario
¿Qué sucede si diferentes compañías desean almacenar diferentes atributos de perfil para sus usuarios? Cada compañía tendrá un conjunto definido de atributos que se aplicarán a todos los usuarios de esa compañía.
Por ejemplo:
- La empresa A quiere almacenar: LIKE_MOVIE (boolean), LIKE_MUSIC (boolean)
- La empresa B quiere almacenar: FAV_CUISINE (String)
- La empresa C quiere almacenar: OWN_DOG (boolean), DOG_COUNT (int)
Enfoque 1
La forma de fuerza bruta es tener un esquema único para el usuario y dejar que tengan valores nulos cuando no pertenecen a la empresa:
ID, COMPANY_ID, FIRST_NAME, LAST_NAME, EMAIL, LIKE_MOVIE, LIKE_MUSIC, FAV_CUISINE, OWN_DOG, DOG_COUNT, CREATED_ON
Lo cual es un poco desagradable porque terminará con una gran cantidad de NULLS y filas de usuarios que tienen columnas que no son relevantes para ellos (es decir, todos los usuarios que pertenecen a la Compañía A tienen valores NULL para FAV_CUISINE, OWN_DOG, DOG_COUNT)
Enfoque 2
Un segundo enfoque es tener un "campo de forma libre":
ID, COMPANY_ID, FIRST_NAME, LAST_NAME, EMAIL, CUSTOM_1, CUSTOM_2, CUSTOM_3, CREATED_ON
Lo cual sería desagradable por sí solo, ya que no tiene idea de qué son los campos personalizados, el tipo de datos no reflejará los valores almacenados (por ejemplo, almacenaremos el valor int como VARCHAR).
Enfoque 3
He investigado el campo PostgreSQL JSON, en cuyo caso tendrá:
ID, COMPANY_ID, FIRST_NAME, LAST_NAME, EMAIL, CUSTOM_PROFILE_JSON, CREATED_ON
En este caso, ¿cómo podría aplicar diferentes esquemas a un usuario? Un usuario con la empresa A tendrá un esquema similar
{"LIKE_MOVIE":"boolean", "LIKE_MUSIC": "boolean"}
Mientras que un usuario con la Compañía C tendrá un esquema diferente:
{"OWN_DOG ":"boolean", "DOG_COUNT": "int"}
¿Cómo debo resolver este problema? ¿Cómo puedo diseñar la base de datos correctamente para permitir este esquema flexible para un solo "objeto" (Usuario) en función de la relación que tienen (Empresa)?
solución relacional? solución nosql?
Editar: También he pensado en una tabla "CUSTOM_PROFILE" que esencialmente almacenará los atributos del usuario en filas en lugar de columnas.
Hay 2 problemas con este enfoque:
1) Los datos crecen por usuario como filas en lugar de columnas, y esto significa que para obtener una imagen completa del usuario, es necesario realizar muchas uniones, varias uniones a la tabla de "perfil personalizado" en los diferentes atributos personalizados
2) El valor de los datos siempre se almacena como VARCHAR para que sea genérico, incluso si sabemos que se supone que los datos son enteros o booleanos, etc.