OK, eu acho que você precisa quebrar isso nas "variedades" básicas.
Você tem dois objetos no estilo "entidade":
User
Campaign
Você tem um objeto de estilo "mapeamento":
UserCampaign
Você tem um objeto de estilo "transacional":
Click
Etapa 1:entidade
Vamos começar com os mais fáceis:
User
&Campaign
. Estes são realmente dois objetos separados, nenhum deles realmente depende do outro para sua existência. Também não há hierarquia implícita entre os dois:os usuários não pertencem às campanhas, nem as campanhas pertencem aos usuários. Quando você tem dois objetos de nível superior como esse, eles geralmente ganham sua própria coleção. Então você vai querer um
Users
coleção e uma Camapaigns
coleção. Etapa 2:mapeamento
UserCampaign
é atualmente usado para representar um mapeamento N-para-M. Agora, em geral, quando você tem um mapeamento N-para-1, você pode colocar o N dentro do 1. No entanto, com o mapeamento N-para-M, você geralmente tem que "escolher um lado". Em teoria, você poderia fazer o seguinte:
- Coloque uma lista de
Campaign ID
s dentro de cadaUser
- Coloque uma lista de
Users ID
s dentro de cadaCampaign
Pessoalmente, eu faria o número 1. Você provavelmente tem muito mais usuários do que campanhas e provavelmente deseja colocar a matriz onde ela será mais curta.
Etapa 3:transacional
Clicks é realmente uma fera completamente diferente. Em termos de objeto, você poderia pensar o seguinte:
Clicks
"pertence a" um User
, Clicks
"pertence a" uma Campaign
. Então, em teoria, você poderia apenas armazenar cliques que fazem parte de qualquer um desses objetos. É fácil pensar que os cliques pertencem em Usuários ou Campanhas. Mas se você realmente se aprofundar, a simplificação acima é realmente falha. Em seu sistema,
Clicks
são realmente um objeto central. Na verdade, você pode até dizer que Usuários e Campanhas são realmente apenas "associados" ao clique. Dê uma olhada nas perguntas / consultas que você está fazendo. Todas essas perguntas realmente giram em torno de cliques. Usuários e campanhas não são o objeto central em seus dados, os cliques são.
Além disso, os cliques serão os dados mais abundantes em seu sistema. Você terá muito mais cliques do que qualquer outra coisa.
Este é o maior problema ao projetar um esquema para dados como este. Às vezes você precisa empurrar objetos "pais" quando eles não são a coisa mais importante. Imagine construir um sistema simples de e-commerce. Está claro que
orders
"pertenceria a" users
, mas orders
é tão central para o sistema que será um objeto de "nível superior". Encerrando
Você provavelmente vai querer três coleções:
- Usuário -> tem uma lista de campanhas._id
- Campanha
- Cliques -> contém user._id, campaign._id
Isso deve satisfazer todas as suas necessidades de consulta:
Veja as informações de cada clique como IP, Referer, OS, etc
db.clicks.find()
Veja quantas vezes os cliques são provenientes do X IP, X Referer, X OS
db.clicks.group()
ou execute um Map-Reduce.
Associar cada clique a um usuário e uma campanha
db.clicks.find({user_id : blah})
Também é possível enviar IDs de clique para usuários e campanhas (se isso fizer sentido). Observe que, se você tiver muitos cliques, realmente terá que analisar as consultas mais executadas. Você não pode indexar em todos os campos, então muitas vezes você vai querer executar Map-Reduces para "agrupar" os dados para essas consultas.