2014-07-15 37 views
19

Tôi cố gắng để làm một cái gì đó giống nhưSelect Group bởi đếm và đếm riêng biệt trong cùng một truy vấn MongoDB

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

Truy vấn này đưa ra kết quả trừ count (biệt subscriber_id)

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

này truy vấn sau đây đưa ra kết quả ngoại trừ số (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} 
       }} 
]) 

nhưng tôi muốn đếm (subscriber_id), đếm (distin ct subscriber_id) trong cùng một kết quả

Trả lời

43

Bạn đang bắt đầu suy nghĩ đúng dòng ở đây khi bạn đi đúng hướng. Thay đổi suy nghĩ SQL của bạn, "khác biệt" thực sự chỉ là một cách khác để viết hoạt động $group bằng một trong hai ngôn ngữ. Điều đó có nghĩa là bạn có hai hoạt động nhóm xảy ra ở đây và, trong cụm từ đường ống tổng hợp, hai giai đoạn đường ống.

Chỉ với các tài liệu đơn giản để hình dung:

{ 
    "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" 
} 

Nó đứng vào lý do đó cho "chiến dịch" kết hợp đưa tổng số và đếm "khác biệt" là "3" và "2" tương ứng. Vì vậy, điều hợp lý cần làm là "nhóm" lên tất cả các giá trị "subscriber_id" trước và giữ số lần xuất hiện cho mỗi, sau đó suy nghĩ "đường ống", "tổng" số lượng trên mỗi "chiến dịch" và sau đó chỉ cần đếm " biệt "xuất hiện như một số riêng biệt:

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 } 
    }} 
]) 

Sau khi người đầu tiên 'nhóm' các tài liệu đầu ra có thể được hình dung như thế này:

{ 
    "_id" : { 
     "campaign_id" : "A", 
     "campaign_name" : "A", 
     "subscriber_id" : "456" 
    }, 
    "count" : 1 
} 
{ 
    "_id" : { 
     "campaign_id" : "A", 
     "campaign_name" : "A", 
     "subscriber_id" : "123" 
    }, 
    "count" : 2 
} 

vì vậy, từ 'ba' tài liệu trong mẫu," 2 "thuộc về một giá trị khác biệt và" 1 "với giá trị khác. Điều này vẫn có thể được đạt với $sum để có được tổng tài liệu phù hợp mà bạn làm trong giai đoạn tiếp theo, với kết quả cuối cùng:

{ 
    "_id" : { 
     "campaign_id" : "A", 
     "campaign_name" : "A" 
    }, 
    "totalCount" : 3, 
    "distinctCount" : 2 
} 

Một loại suy thực sự tốt cho đường ống kết hợp là ống unix "|" nhà điều hành, cho phép "chuỗi" các hoạt động để bạn có thể truyền đầu ra của một lệnh thông qua đầu vào của lệnh tiếp theo, v.v. Bắt đầu nghĩ về các yêu cầu xử lý của bạn theo cách đó sẽ giúp bạn hiểu các hoạt động với đường ống tổng hợp tốt hơn.

+0

Cảm ơn bạn, câu trả lời rất hữu ích với đẹp giải thích – Rams

+1

Yeah, tôi đã sử dụng tổng hợp trong một thời gian và không bao giờ hiểu nó cho đến bây giờ. Tôi chỉ tránh được sự phức tạp của khía cạnh đường ống của đường ống hoàn toàn, bởi vì tài liệu của mongoDB khá khó hiểu về điều này và cần ví dụ của bạn! –

1

SQL Query: (nhóm bởi & đếm riêng biệt)

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

Truy vấn Mongo tương đương sẽ trông như thế này:

db.TransactionDetails.aggregate([ 
{$group:{_id:{"CITY" : "$cityName"},uniqueCount: {$addToSet: "$emailId"}}}, 
{$project:{"CITY":1,uniqueCustomerCount:{$size:"$uniqueCount"}} } 
]); 
Các vấn đề liên quan