Stai cominciando a pensare lungo le linee giuste mentre ti dirigevi nella giusta direzione. Cambiando la tua mentalità SQL, "distinto" è in realtà solo un altro modo di scrivere un'operazione in $group
in entrambe le lingue. Ciò significa che hai due operazioni di gruppo che si verificano qui e, in termini di pipeline di aggregazione, due fasi di pipeline.
Basta con i documenti semplificati di visualizzare:
{
"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"
}
E 'ovvio che per il dato "campagna" combinazione il conteggio totale e il conteggio "distinta" sono "3" e "2", rispettivamente. Quindi la cosa logica da fare è "raggruppare" tutti quei valori "subscriber_id" e tenere il conteggio delle occorrenze per ciascuno, poi mentre pensi "pipeline", "total" quei conteggi per "campagna" e poi conta solo i " "eventi come un numero separato:
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 }
}}
])
Dopo il primo 'distinte gruppo' documenti di output possono essere visualizzati in questo modo:
{
"_id" : {
"campaign_id" : "A",
"campaign_name" : "A",
"subscriber_id" : "456"
},
"count" : 1
}
{
"_id" : {
"campaign_id" : "A",
"campaign_name" : "A",
"subscriber_id" : "123"
},
"count" : 2
}
Così da 'tre' documenti nel campione," 2 "appartengono a un valore distinto e" 1 "a un altro. Questo può ancora essere pari con $sum
al fine di ottenere i documenti di corrispondenza totale, che si fanno nella fase successiva, con il risultato finale:
{
"_id" : {
"campaign_id" : "A",
"campaign_name" : "A"
},
"totalCount" : 3,
"distinctCount" : 2
}
Un davvero buona analogia per il gasdotto di aggregazione è il tubo unix "|" operatore, che consente il "concatenamento" delle operazioni in modo da poter passare l'output di un comando fino all'input del successivo e così via. Iniziare a pensare ai requisiti di elaborazione in questo modo ti aiuterà a capire meglio le operazioni con la pipeline di aggregazione.
Grazie, risposta molto utile con bella spiegazione – Rams
Sì, lo Ho usato l'aggregato per un po 'e non l'ho mai capito fino ad ora. Avevo semplicemente evitato del tutto la complessità dell'aspetto dei tubi delle pipeline, perché i documenti di mongoDB sono piuttosto confusi su questo e hanno bisogno del tuo esempio! –