あなたは正しい方向に向かっていたので、ここで正しい線に沿って考え始めています。 SQLの考え方を変えると、「個別」は実際には $group
を記述するもう1つの方法にすぎません。 いずれかの言語での操作。つまり、2つあります ここで発生するグループ操作と、集約パイプラインの用語では、2つのパイプラインステージ。
視覚化するための簡略化されたドキュメントだけで:
{
"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"
}
与えられた「キャンペーン」の組み合わせについて、合計数と「個別」数がそれぞれ「3」と「2」であるのは当然のことです。したがって、論理的に行うべきことは、最初にすべての「subscriber_id」値を「グループ化」してそれぞれの発生数を保持し、次に「パイプライン」を考えながら、「キャンペーン」ごとにそれらの数を「合計」してから、「別個の番号としての別個の」出現:
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 }
}}
])
最初の「グループ」の後、出力ドキュメントは次のように視覚化できます。
{
"_id" : {
"campaign_id" : "A",
"campaign_name" : "A",
"subscriber_id" : "456"
},
"count" : 1
}
{
"_id" : {
"campaign_id" : "A",
"campaign_name" : "A",
"subscriber_id" : "123"
},
"count" : 2
}
したがって、サンプルの「3つの」ドキュメントから、「2」は1つの異なる値に属し、「1」は別の値に属します。これは、 $sum
で合計できます。 次の段階で行う一致するドキュメントの合計を取得し、最終結果を得るには:
{
"_id" : {
"campaign_id" : "A",
"campaign_name" : "A"
},
"totalCount" : 3,
"distinctCount" : 2
}
アグリゲーションパイプラインの非常に良い例えは、unixパイプ「|」です。演算子。これにより、操作の「連鎖」が可能になり、あるコマンドの出力を次のコマンドの入力に渡すことができます。このように処理要件について考え始めると、集約パイプラインを使用した操作をよりよく理解するのに役立ちます。