2013-07-23 5 views
1

J'utilise le schéma suivant de la mongodb FAQ:Comment grouper dans mongo db sur les attributs dynamiques avec le framework d'agrégation?

{ 
    attrib : [ 
     { k: "color", v: "red" }, 
     { k: "shape", v: "rectangle" }, 
     { k: "color", v: "blue" }, 
     { k: "avail", v: true } 
     ] 
} 

Comment puis-je compter groupe et la collection par exemple par "couleur"? Je préférerais utiliser le cadre d'agrégation si possible au lieu de réduire la carte.

Mon résultat devrait ressembler à ceci:

[ 
    { 
     v: "blue", 
     count: 5 
    }, 
    { 
     v: "red", 
     count: 2 
    }, 
    { 
     v: "black", 
     count: 52 
    } 
] 
+0

Pouvez-vous être un peu plus descriptif sur les documents que vous en entrée et ce que vous attendez en sortie? – Derick

+0

Si vous voulez juste compter les documents, essayez '.find ({" attrib.k ":" color "}). Count()'. Si vous voulez quelque chose de plus complexe comme le nombre d'occurrences dans les documents, veuillez fournir plus d'informations, telles que la sortie attendue :) – randunel

+0

Je viens d'ajouter ma sortie attendue. – joafeldmann

Répondre

2

Ceci est assez trivial, nous devons faire un dérouleur, match, puis un groupe par:

db.so.aggregate([ 
    { $unwind : '$attrib' }, 
    { $match: { 'attrib.k' : 'color' } }, 
    { $group: { _id: '$attrib.v', count: { '$sum': 1 } } } 
]); 

Déroulez souffle le " tableau attrib » dans un document par élément de tableau:

{ 
    "result" : [ 
     { 
      "_id" : ObjectId("51eeb9f2812db9ff4412f132"), 
      "attrib" : { 
       "k" : "color", 
       "v" : "red" 
      } 
     }, 
     { 
      "_id" : ObjectId("51eeb9f2812db9ff4412f132"), 
      "attrib" : { 
       "k" : "shape", 
       "v" : "rectangle" 
      } 
     }, 
     { 
      "_id" : ObjectId("51eeb9f2812db9ff4412f132"), 
      "attrib" : { 
       "k" : "color", 
       "v" : "blue" 
      } 
     }, 
     { 
      "_id" : ObjectId("51eeb9f2812db9ff4412f132"), 
      "attrib" : { 
       "k" : "avail", 
       "v" : true 
      } 
     } 
    ], 
    "ok" : 1 
} 

match supprime alors tous les éléments non couleur:

{ 
    "result" : [ 
     { 
      "_id" : ObjectId("51eeb9f2812db9ff4412f132"), 
      "attrib" : { 
       "k" : "color", 
       "v" : "red" 
      } 
     }, 
     { 
      "_id" : ObjectId("51eeb9f2812db9ff4412f132"), 
      "attrib" : { 
       "k" : "color", 
       "v" : "blue" 
      } 
     } 
    ], 
    "ok" : 1 
} 

Et le groupe fait enfin revenir:

{ 
    "result" : [ 
     { 
      "_id" : "blue", 
      "count" : 1 
     }, 
     { 
      "_id" : "red", 
      "count" : 1 
     } 
    ], 
    "ok" : 1 
} 

(Toutes les sorties ci-dessus est juste de vous seul document exemple)

+0

Merci! Pensez-vous que l'utilisation du framework d'agrégation est meilleure/plus rapide que l'utilisation de map/reduce pour cela? – joafeldmann

+0

Oui, car il ne va pas dans JavaScript de cette façon. – Derick

+0

Une autre question: Comment inclure/grouper aussi les objets, où l'attribut de couleur n'existe pas du tout? – joafeldmann