OK, je pense que vous devez diviser cela en "variétés" de base.
Vous avez deux objets de style "entité" :
User
Campaign
Vous avez un objet de style "mappage" :
UserCampaign
Vous avez un objet de style "transactionnel" :
Click
Étape 1 :entité
Commençons par les plus simples :User
&Campaign
. Ce sont vraiment deux objets distincts, aucun ne dépend vraiment de l'autre pour son existence. Il n'y a pas non plus de hiérarchie implicite entre les deux :les utilisateurs n'appartiennent pas aux campagnes, et les campagnes n'appartiennent pas non plus aux utilisateurs.
Lorsque vous avez deux objets de niveau supérieur comme celui-ci, ils gagnent généralement leur propre collection. Donc, vous aurez besoin d'un Users
collection et une Camapaigns
collecte.
Étape 2 :mappage
UserCampaign
est actuellement utilisé pour représenter un mappage N vers M. Maintenant, en général, lorsque vous avez un mappage N à 1, vous pouvez mettre le N à l'intérieur du 1. Cependant, avec le mappage N à M, vous devez généralement "choisir un côté".
En théorie, vous pourriez faire l'une des choses suivantes :
- Mettre une liste d'
Campaign ID
s à l'intérieur de chaqueUser
- Mettre une liste d'
Users ID
s à l'intérieur de chaqueCampaign
Personnellement, je ferais le n°1. Vous avez probablement beaucoup plus d'utilisateurs que de campagnes, et vous souhaitez probablement placer le tableau là où il sera le plus court.
Étape 3 :transactionnel
Clicks est vraiment une bête complètement différente. En termes d'objet, vous pourriez penser à ce qui suit :Clicks
"appartiennent" à un User
, Clicks
"appartiennent" à une Campaign
. Donc, en théorie, vous pourriez simplement stocker les clics faisant partie de l'un ou l'autre de ces objets. Il est facile de penser que les clics appartiennent à Utilisateurs ou Campagnes.
Mais si vous creusez vraiment plus profondément, la simplification ci-dessus est vraiment imparfaite. Dans votre système, Clicks
sont vraiment un objet central. En fait, vous pourriez même dire que les utilisateurs et les campagnes sont simplement "associés" au clic.
Jetez un œil aux questions / requêtes que vous posez. Toutes ces questions tournent en fait autour des clics. Les utilisateurs et les campagnes ne sont pas l'objet central de vos données, ce sont les clics.
De plus, les clics seront les données les plus abondantes de votre système. Vous allez avoir bien plus de clics qu'autre chose.
C'est le plus gros problème lors de la conception d'un schéma pour des données comme celle-ci. Parfois, vous devez repousser les objets "parents" alors qu'ils ne sont pas la chose la plus importante. Imaginez la construction d'un système de commerce électronique simple. Il est clair que les orders
"appartiennent" aux users
, mais orders
est si central au système qu'il va être un objet "de niveau supérieur".
En conclusion
Vous aurez probablement besoin de trois collections :
- Utilisateur -> a la liste de la campagne._id
- Campagne
- Clics -> contient user._id, campaign._id
Cela devrait répondre à tous vos besoins de requête :
Voir les informations de chaque clic comme IP, Referer, OS, etc
db.clicks.find()
Voyez combien de clics proviennent souvent de X IP, X Referer, X OS
db.clicks.group()
ou lancez un Map-Reduce.
Associez chaque clic à un utilisateur et à une campagne
db.clicks.find({user_id : blah})
Il est également possible d'envoyer des ID de clic aux utilisateurs et aux campagnes (si cela a du sens).
Veuillez noter que si vous avez beaucoup, beaucoup de clics, vous devrez vraiment analyser les requêtes que vous lancez le plus. Vous ne pouvez pas indexer sur chaque champ, vous voudrez donc souvent exécuter Map-Reduces pour "cumuler" les données de ces requêtes.