2013-08-29 3 views
16

Я пытаюсь написать агрегацию для идентификации учетных записей, в которых используются несколько источников оплаты. Типичные данные.MongoDB Aggregation: подсчет различных полей

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

Теперь я хотел бы получить список учетных записей, подобных этой

{ 
account:"abc", 
vendorCount:2 
} 

Как бы я пишу это в рамках агрегации Mongo в

ответ

46

Я понял это с помощью $ addToSet и $ unwind.

Mongodb Aggregation count array/set size

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

Надеется, что это помогает кому-то

+0

Это может работать для множеств, где радушие множества достаточно мал, но для больших сценариев данных это не будет работать (представьте себе, если у вас были сотни тысяч уникальных поставщиков). –

+3

Этот ответ решает большой сценарий данных: http://stackoverflow.com/a/24770233/139721 – anushr

+0

Действительно ли нужно вернуться к повторению «$ vendors» снова? учитывая тот факт, что мы можем вычислить количество поставщиков с помощью 'results.get (« vendors »). size();' –

14

Я думаю, что его лучше, если вы выполняете запрос, как следующие, который позволит избежать разматывания

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

который покажет вам следующий результат, который, как ожидается, ,

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

Я не понимаю, почему кто-то должен использовать $ группу дважды

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

Это будет работать прекрасно.

+0

Я предполагал, что они хотели переименовать ключи и переформатировать. Но это действительно намного лучше и эффективнее. – c24b

+9

Я думаю, что они искали 'уникальный' счет. – user1700890

-4

Пример

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

Вы должны предоставить описание для описания * почему * это работает как решение вопроса. Также очень полезно сделать пример кода, используя тот же контекст данных и переменных, что и фактический вопрос. Этот ответ будет считаться «низким качеством» в StackOverflow; ответы низкого качества, как правило, привлекают downvotes, и могут заставить вас не отвечать на любые другие вопросы. –

0

Вы можете использовать sets

db.test.aggregate([ 
    {$group: { 
     _id: "$account", 
     uniqueVendors: {$addToSet: "$vendor"} 
    }}, 
    {$project: { 
     _id: 1, 
     vendorsCount: {$size: "$uniqueVendors"} 
    }} 
]);