web-dev-qa-db-ja.com

同じmongodbクエリでカウントと個別カウントでグループ化を選択します

私は次のようなことをしようとしています

select campaign_id,campaign_name,count(subscriber_id),count(distinct subscriber_id)
group by campaign_id,campaign_name from campaigns;

Count(distinct subscriber_id)を除く結果を提供するこのクエリ

db.campaigns.aggregate([
    {$match: {subscriber_id: {$ne: null}}},
    {$group: { 
        _id: {campaign_id: "$campaign_id",campaign_name: "$campaign_name"},
        count: {$sum: 1}
    }}
])

Count(subscriber_id)を除く結果を与える次のクエリ

db.campaigns_logs.aggregate([
    {$match : {subscriber_id: {$ne: null}}},
    {$group : { _id: {campaign_id: "$campaign_id",campaign_name: "$campaign_name",subscriber_id: "$subscriber_id"}}},
    {$group : { _id: {campaign_id: "$campaign_id",campaign_name: "$campaign_name"}, 
                count: {$sum: 1}
              }}
])

しかし、同じ結果でcount(subscriber_id)、count(distinct subscriber_id)が欲しい

22
Rams

あなたは正しい方向に向かっていたので、ここで正しい線に沿って考え始めています。 SQLの考え方を変えると、「個別」は、いずれかの言語で $group 操作を記述する別の方法にすぎません。つまり、ここで発生するtwoグループ操作があり、集約パイプラインの用語では、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パイプ「|」です。演算子。操作の「連鎖」を可能にして、あるコマンドの出力を次のコマンドの入力に渡すことができる、などです。そのように処理要件を考え始めると、集約パイプラインの操作をよりよく理解するのに役立ちます。

58
Neil Lunn

SQLクエリ:(グループ化と個別のカウント)

select city,count(distinct(emailId)) from TransactionDetails group by city;

同等のmongoクエリは次のようになります。

db.TransactionDetails.aggregate([ 
{$group:{_id:{"CITY" : "$cityName"},uniqueCount: {$addToSet: "$emailId"}}},
{$project:{"CITY":1,uniqueCustomerCount:{$size:"$uniqueCount"}} } 
]);