2013-08-29 35 views
16

Tôi đang cố viết một tập hợp để xác định các tài khoản sử dụng nhiều nguồn thanh toán. Dữ liệu điển hình sẽ là.Tập hợp MongoDB: Đếm các trường riêng biệt

{ 
account:"abc", 
vendor:"amazon", 
} 
... 
{ 
account:"abc", 
vendor:"overstock", 
} 

Bây giờ, tôi muốn tạo ra một danh sách các tài khoản tương tự như sau

{ 
account:"abc", 
vendorCount:2 
} 

Làm thế nào tôi sẽ viết những dòng này trong khuôn khổ hợp Mongo của

Trả lời

46

tôi figured này ra bằng $ addToSet và $ các nhà khai thác thư giãn.

Mongodb Aggregation count array/set size

db.collection.aggregate([ 
{ 
    $group: { _id: { account: '$account' }, vendors: { $addToSet: '$vendor'} } 
}, 
{ 
    $unwind:"$vendors" 
}, 
{ 
    $group: { _id: "$_id", vendorCount: { $sum:1} } 
} 
]); 

Hy vọng nó sẽ giúp người

+0

Điều này có thể làm việc cho bộ nơi thân mật của bộ này là đủ nhỏ, nhưng đối với kịch bản dữ liệu lớn này sẽ không hoạt động (hãy tưởng tượng nếu bạn đã có hàng trăm nghìn nhà cung cấp duy nhất). –

+3

Câu trả lời này giải quyết được tình huống dữ liệu lớn: http://stackoverflow.com/a/24770233/139721 – anushr

+0

Có thực sự cần thiết phải quay trở lại để lặp lại '$ vendor' một lần nữa? cho rằng thực tế chúng ta có thể tính toán số lượng nhà cung cấp bởi 'results.get (" vendor "). size();' –

14

Tôi nghĩ tốt hơn nếu bạn thực hiện truy vấn của nó như sau đó sẽ tránh Thư giãn

db.t2.insert({_id:1,account:"abc",vendor:"amazon"}); 
db.t2.insert({_id:2,account:"abc",vendor:"overstock"}); 


db.t2.aggregate(
{ $group : { _id : { "account" : "$account", "vendor" : "$vendor" }, number : { $sum : 1 } } }, 
{ $group : { _id : "$_id.account", number : { $sum : 1 } } } 
); 

nào sẽ cho bạn thấy sau kết quả dự kiến .

{ "_id" : "abc", "number" : 2 } 
5

Tôi không hiểu tại sao ai đó sẽ phải sử dụng $ nhóm hai lần

db.t2.aggregate([ { $group: {"_id":"$account" , "number":{$sum:1}} } ]) 

này sẽ làm việc hoàn toàn tốt đẹp.

+0

Tôi cho là vì họ muốn đổi tên các khóa và định dạng lại. Nhưng điều này, thực sự, tốt hơn và hiệu quả hơn nhiều. – c24b

+9

Tôi nghĩ rằng họ đang tìm kiếm số lượng 'duy nhất'. – user1700890

-4

Một ví dụ

db.collection.distinct("example.item").forEach(function(docs) { 
    print(docs + "==>>" + db.collection.count({"example.item":docs})) 
}); 
+1

Bạn nên cung cấp mô tả để mô tả * lý do * điều này hoạt động như một giải pháp cho câu hỏi. Nó cũng rất, rất hữu ích để làm cho mã ví dụ sử dụng cùng một bối cảnh dữ liệu và biến như câu hỏi thực tế. Câu trả lời này sẽ được coi là "chất lượng thấp" trên StackOverflow; các câu trả lời có chất lượng thấp có xu hướng thu hút các phiếu giảm giá và có thể khiến bạn bị cấm trả lời bất kỳ câu hỏi nào khác. –

0

Bạn có thể sử dụng sets

db.test.aggregate([ 
    {$group: { 
     _id: "$account", 
     uniqueVendors: {$addToSet: "$vendor"} 
    }}, 
    {$project: { 
     _id: 1, 
     vendorsCount: {$size: "$uniqueVendors"} 
    }} 
]); 
Các vấn đề liên quan