Začínáte uvažovat správným směrem, protože jste se vydali správným směrem. Změna vašeho myšlení SQL, „odlišný“ je ve skutečnosti jen další způsob psaní $group
provoz v obou jazycích. To znamená, že máte dva skupinové operace, které se zde odehrávají, a z hlediska agregačního potrubí dvě fáze potrubí.
Pouze se zjednodušenými dokumenty k vizualizaci:
{
"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"
}
Je logické, že pro danou kombinaci „kampaně“ je celkový počet a „odlišný“ počet „3“ a „2“. Logická věc, kterou je třeba udělat, je nejprve „seskupit“ všechny tyto hodnoty „subscriber_id“ a ponechat počet výskytů pro každou z nich, pak při přemýšlení „potrubí“ „celkem“ tyto počty za „kampaň“ spočítat odlišné" výskyty jako samostatné číslo:
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 }
}}
])
Po první "skupině" mohou být výstupní dokumenty vizualizovány takto:
{
"_id" : {
"campaign_id" : "A",
"campaign_name" : "A",
"subscriber_id" : "456"
},
"count" : 1
}
{
"_id" : {
"campaign_id" : "A",
"campaign_name" : "A",
"subscriber_id" : "123"
},
"count" : 2
}
Takže ze „tří“ dokumentů ve vzorku patří „2“ jedné odlišné hodnotě a „1“ jiné. Stále to lze sečíst pomocí $sum
abyste získali celkový počet odpovídajících dokumentů, které provedete v následující fázi, s konečným výsledkem:
{
"_id" : {
"campaign_id" : "A",
"campaign_name" : "A"
},
"totalCount" : 3,
"distinctCount" : 2
}
Opravdu dobrou analogií pro agregační kanál je unixové potrubí "|" operátor, který umožňuje "řetězení" operací, takže můžete předat výstup jednoho příkazu na vstup dalšího a tak dále. Začnete-li přemýšlet o svých požadavcích na zpracování tímto způsobem, pomůže vám to lépe porozumět operacím s agregačním kanálem.