Esta questão é sobre como devo projetar um banco de dados, ele pode ser um banco de dados relacional / nosql, dependendo de qual será a melhor solução
Dado um requisito, você precisará criar um sistema que envolva um banco de dados para rastrear "Empresa" e "Usuário". Um único usuário sempre pertence apenas a uma empresa
- Um usuário pode pertencer apenas a uma empresa
- Uma empresa pode ter muitos usuários
O design da tabela "Empresa" é bastante direto. A empresa terá os seguintes atributos / colunas: (vamos simplificar)
ID, COMPANY_NAME, CREATED_ON
Primeiro cenário
Simples e direto, todos os usuários têm o mesmo atributo, portanto, isso pode ser feito facilmente no estilo relacional, tabela de usuários:
ID, COMPANY_ID, FIRST_NAME, LAST_NAME, EMAIL, CREATED_ON
Segundo cenário
O que acontece se diferentes empresas quiserem armazenar atributos de perfil diferentes para seus usuários. Cada empresa terá um conjunto definido de atributos que se aplicariam a todos os usuários dessa empresa.
Por exemplo:
- A empresa A deseja armazenar: LIKE_MOVIE (booleano), LIKE_MUSIC (booleano)
- A empresa B deseja armazenar: FAV_CUISINE (String)
- A empresa C deseja armazenar: OWN_DOG (booleano), DOG_COUNT (int)
Abordagem 1
a maneira da força bruta é ter um esquema único para o usuário e permitir que eles tenham nulos quando não pertencem à empresa:
ID, COMPANY_ID, FIRST_NAME, LAST_NAME, EMAIL, LIKE_MOVIE, LIKE_MUSIC, FAV_CUISINE, OWN_DOG, DOG_COUNT, CREATED_ON
O que é meio desagradável, porque você terá muitos NULLS e linhas de usuário que têm colunas que são irrelevantes para eles (ou seja, todos os usuários pertencentes à empresa A têm valores NULL para FAV_CUISINE, OWN_DOG, DOG_COUNT)
Abordagem 2
uma segunda abordagem, é ter "campo de forma livre":
ID, COMPANY_ID, FIRST_NAME, LAST_NAME, EMAIL, CUSTOM_1, CUSTOM_2, CUSTOM_3, CREATED_ON
O que seria desagradável por si só, já que você não tem idéia do que são campos personalizados, o tipo de dados não refletirá os valores armazenados (por exemplo, armazenaremos o valor int como VARCHAR).
Abordagem 3
Eu examinei o campo JSON do PostgreSQL; nesse caso, você terá:
ID, COMPANY_ID, FIRST_NAME, LAST_NAME, EMAIL, CUSTOM_PROFILE_JSON, CREATED_ON
Nesse caso, como você seria capaz de aplicar esquemas diferentes a um usuário? Um usuário da empresa A terá um esquema parecido com
{"LIKE_MOVIE":"boolean", "LIKE_MUSIC": "boolean"}
Enquanto um usuário com a empresa C terá um esquema diferente:
{"OWN_DOG ":"boolean", "DOG_COUNT": "int"}
Como devo resolver esse problema? Como posso projetar o banco de dados corretamente para permitir esse esquema flexível para um único "objeto" (Usuário) com base no relacionamento que eles têm (Empresa)?
solução relacional? solução nosql?
Editar: Eu também pensei em uma tabela "CUSTOM_PROFILE" que essencialmente armazena atributos do usuário em linhas e não em colunas.
Existem 2 problemas com esta abordagem:
1) Os dados crescem por usuário, à medida que as linhas aumentam, em vez de colunas - e isso significa que, para obter uma imagem completa do usuário, muitas associações precisam ser feitas, várias associações à tabela "perfil personalizado" nos diferentes atributos personalizados
2) O valor dos dados é sempre armazenado como VARCHAR para ser genérico, mesmo se sabemos que os dados devem ser inteiros ou booleanos, etc.