OK, jag tror att du måste dela upp det här i de grundläggande "varianterna".
Du har två objekt i "entitetsstil":
User
Campaign
Du har ett objekt i "mappningsstil":
UserCampaign
Du har ett objekt i "transaktionsstil":
Click
Steg 1:enhet
Låt oss börja med de enkla:User
&Campaign
. Dessa är verkligen två separata objekt, varken det ena beror egentligen på det andra för sin existens. Det finns inte heller någon implicit arvegång mellan de två:Användare tillhör inte kampanjer och inte heller kampanjer tillhör användare.
När du har två sådana här objekt på toppnivå, tjänar de vanligtvis sin egen samling. Så du vill ha en User
samling och en Camapaigns
samling.
Steg 2:kartläggning
UserCampaign
används för närvarande för att representera en N-till-M-mappning. Nu, i allmänhet, när du har en N-till-1-mappning, kan du sätta N inuti 1:an. Men med N-till-M-mappningen måste du vanligtvis "välja en sida".
I teorin kan du göra något av följande:
- Sätt in en lista med
Campaign ID
s inuti varjeUser
- Sätt in en lista med
Users ID
s inuti varjeCampaign
Personligen skulle jag göra #1. Du har förmodligen mycket fler användare som kampanjer, och du vill förmodligen placera arrayen där den blir kortare.
Steg 3:transaktionell
Clicks är verkligen en helt annan best. I objekttermer kan du tänka följande:Clicks
"tillhör" en User
, Clicks
"tillhör" en Campaign
. Så i teorin kan du bara lagra klick som är en del av något av dessa objekt. Det är lätt att tro att klick hör under Användare eller kampanjer.
Men om du verkligen gräver djupare är ovanstående förenkling verkligen bristfällig. I ditt system, Clicks
är verkligen ett centralt objekt. Faktum är att du kanske till och med kan säga att användare och kampanjer egentligen bara är "associerade med" klicket.
Ta en titt på frågorna/frågorna du ställer. Alla dessa frågor kretsar faktiskt kring klick. Användare och kampanjer är inte det centrala objektet i din data, det är Klick.
Dessutom kommer klick att vara den mest rikliga informationen i ditt system. Du kommer att få mycket fler klick än något annat.
Detta är det största problemet när man utformar ett schema för data som denna. Ibland behöver du trycka bort "förälder"-objekt när de inte är det viktigaste. Föreställ dig att bygga ett enkelt e-handelssystem. Det är tydligt att orders
skulle "tillhöra" users
, men orders
är så centralt i systemet att det kommer att bli ett objekt på "toppnivå".
Slutar ihop det
Du vill förmodligen ha tre samlingar:
- Användare -> har en lista över kampanj._id
- Kampanj
- Klick -> innehåller user._id, campaign._id
Detta bör tillfredsställa alla dina frågebehov:
Se informationen från varje klick som IP, Referer, OS, etc.
db.clicks.find()
Se hur många klick som kommer från X IP, X Referer, X OS
db.clicks.group()
eller kör en Map-Reduce.
Koppla varje klick till en användare och en kampanj
db.clicks.find({user_id : blah})
Det är också möjligt att skjuta in klick-ID:n till både användare och kampanjer (om det är vettigt).
Observera att om du har många och många klick, måste du verkligen analysera de frågor du kör mest. Du kan inte indexera på alla fält, så du vill ofta köra Map-Reduces för att "rulla upp" data för dessa frågor.