2013-08-29 6 views
16

J'essaie d'écrire une agrégation pour identifier les comptes qui utilisent plusieurs sources de paiement. Les données typiques seraient.Agrégation MongoDB: Comptage des champs distincts

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

Maintenant, je voudrais produire une liste de comptes similaires à ce

{ 
account:"abc", 
vendorCount:2 
} 

Comment puis-je écrire ce dans le cadre d'agrégation de Mongo

Répondre

46

je me suis dit cela en utilisant le $ AddToSet et $ déroulent les opérateurs.

Mongodb Aggregation count array/set size

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

espère que cela aide quelqu'un

+0

Cela peut fonctionner pour les jeux où la cordialité de l'ensemble est assez petit, mais pour les grands scénarios de données cela ne fonctionnera pas (imaginez si vous avez eu des centaines de milliers de fournisseurs uniques). –

+3

Cette réponse résout le scénario de Big Data: http://stackoverflow.com/a/24770233/139721 – anushr

+0

Est-il vraiment nécessaire de revenir à itérer '$ vendeurs 'à nouveau? compte tenu du fait que nous pouvons calculer le nombre de vendeurs par 'results.get (" vendeurs "). size();' –

14

Je pense que mieux si vous exécutez la requête comme suit ce qui évitera dérouleur

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

qui vous montrera résultat suivant qui est prévu .

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

Je ne vois pas pourquoi quelqu'un devrait utiliser $ groupe deux fois

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

Cela fonctionne parfaitement bien.

+0

Je suppose parce qu'ils voulaient renommer les clés et reformater. Mais c'est, en effet, beaucoup mieux et beaucoup efficace. – c24b

+9

Je pense qu'ils cherchaient un compte 'unique'. – user1700890

-4

Un exemple

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

Vous devez fournir une description pour décrire * pourquoi * cela fonctionne comme une solution à la question. Il est également très, très utile de faire en sorte que l'exemple de code utilise les mêmes données et le même contexte que la question réelle. Cette réponse serait considérée comme "de mauvaise qualité" sur StackOverflow; les réponses de mauvaise qualité ont tendance à attirer les downvotes et peuvent vous empêcher de répondre à d'autres questions. –

0

Vous pouvez utiliser sets

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