Je begint hier in de goede richting te denken terwijl je in de goede richting ging. Je SQL-mentaliteit veranderen, "distinct" is eigenlijk gewoon een andere manier om een $group
te schrijven bediening in beide talen. Dat betekent dat je twee . hebt groepsoperaties die hier plaatsvinden en, in termen van aggregatiepijplijn, twee pijplijnfasen.
Gewoon met vereenvoudigde documenten om te visualiseren:
{
"campaign_id": "A",
"campaign_name": "A",
"subscriber_id": "123"
},
{
"campaign_id": "A",
"campaign_name": "A",
"subscriber_id": "123"
},
{
"campaign_id": "A",
"campaign_name": "A",
"subscriber_id": "456"
}
Het spreekt vanzelf dat voor de gegeven "campagne"-combinatie het totale aantal en het "onderscheiden" aantal respectievelijk "3" en "2" zijn. Dus het logische om te doen is eerst al die "subscriber_id" -waarden "groeperen" en het aantal exemplaren voor elk bijhouden, dan terwijl u "pijplijn" denkt, "totaal" die tellingen per "campagne" en dan gewoon de "telt" onderscheiden" voorvallen als een apart nummer:
db.campaigns.aggregate([
{ "$match": { "subscriber_id": { "$ne": null }}},
// Count all occurrences
{ "$group": {
"_id": {
"campaign_id": "$campaign_id",
"campaign_name": "$campaign_name",
"subscriber_id": "$subscriber_id"
},
"count": { "$sum": 1 }
}},
// Sum all occurrences and count distinct
{ "$group": {
"_id": {
"campaign_id": "$_id.campaign_id",
"campaign_name": "$_id.campaign_name"
},
"totalCount": { "$sum": "$count" },
"distinctCount": { "$sum": 1 }
}}
])
Na de eerste "groep" kunnen de uitvoerdocumenten als volgt worden gevisualiseerd:
{
"_id" : {
"campaign_id" : "A",
"campaign_name" : "A",
"subscriber_id" : "456"
},
"count" : 1
}
{
"_id" : {
"campaign_id" : "A",
"campaign_name" : "A",
"subscriber_id" : "123"
},
"count" : 2
}
Dus van de "drie" documenten in het voorbeeld, behoren "2" tot de ene afzonderlijke waarde en "1" tot de andere. Dit kan nog steeds worden opgeteld met $sum
om de totale overeenkomende documenten te krijgen die u in de volgende fase doet, met het uiteindelijke resultaat:
{
"_id" : {
"campaign_id" : "A",
"campaign_name" : "A"
},
"totalCount" : 3,
"distinctCount" : 2
}
Een echt goede analogie voor de aggregatiepijplijn is de unix-pijp "|" operator, waarmee u bewerkingen kunt "ketenen" zodat u de uitvoer van de ene opdracht kunt doorgeven aan de invoer van de volgende, enzovoort. Als u op die manier begint na te denken over uw verwerkingsvereisten, krijgt u een beter inzicht in de bewerkingen met de aggregatiepijplijn.