Cadre | groupe d'agrégation de Mongodb sur des valeurs multiples?

je voudrais utiliser mongoDB d'Agrégation du Cadre pour exécuter ce que dans SQL serait un peu comme:

SELECT SUM(A), B, C from myTable GROUP BY B, C;

Les docs de l'état:

vous pouvez spécifier un seul champ à partir des documents dans le pipeline, une valeur calculée précédemment, ou une clé agrégée composée de plusieurs champs entrants.

mais il n'est pas clair ce que "une clé agrégée faite à partir de plusieurs champs entrants" est réellement?

mon ensemble de données est un peu comme ceci:

[{ "timeStamp" : 1341834988666, "label" : "sharon", "responseCode" : "200", "value" : 10, "success" : "true"},
{ "timeStamp" : 1341834988676, "label" : "paul", "responseCode" : "200", "value" : 60, "success" : "true"},
{ "timeStamp" : 1341834988686, "label" : "paul", "responseCode" : "404", "value" : 15, "success" : "true"},
{ "timeStamp" : 1341834988696, "label" : "sharon", "responseCode" : "200", "value" : 35, "success" : "false"},
{ "timeStamp" : 1341834988166, "label" : "paul", "responseCode" : "200", "value" : 40, "success" : "true"},
{ "timeStamp" : 1341834988266, "label" : "paul", "responseCode" : "404", "value" : 99, "success" : "false"}]

Ma requête ressemble à ceci:

resultsCollection.aggregate(
    { $match : { testid : testid} },
    { $skip : alreadyRead },
    { $project : {
            timeStamp : 1 ,
            label : 1,
            responseCode : 1 ,
            value : 1,
            success : 1
        }},
    { $group : {
            _id : "$label",
            max_timeStamp : { $timeStamp : 1 },
            count_responseCode : { $sum : 1 },
            avg_value : { $sum : "$value" },
            count_success : { $sum : 1 }
        }},
    { $group : {
            ?
        }}
);

mon instinct était d'essayer de faire passer les résultats à un second groupe, je sais que vous pouvez le faire mais cela ne marchera pas parce que le premier groupe réduit déjà trop l'ensemble de données et le niveau de détail requis est perdu.

ce que je veux faire c'est grouper en utilisant label,responseCode et success et obtenir la somme de la valeur du résultat. Il devrait ressembler un peu:

label   | code | success | sum_of_values | count
sharon  | 200  |  true   |      10       |   1
sharon  | 200  |  false  |      35       |   1
paul    | 200  |  true   |      100      |   2
paul    | 404  |  true   |      15       |   1
paul    | 404  |  false  |      99       |   1

où il y en a cinq groupes:

1. { "timeStamp" : 1341834988666, "label" : "sharon", "responseCode" : "200", "value" : 10, "success" : "true"}

2. { "timeStamp" : 1341834988696, "label" : "sharon", "responseCode" : "200", "value" : 35, "success" : "false"}

3. { "timeStamp" : 1341834988676, "label" : "paul", "responseCode" : "200", "value" : 60, "success" : "true"}
   { "timeStamp" : 1341834988166, "label" : "paul", "responseCode" : "200", "value" : 40, "success" : "true"}

4. { "timeStamp" : 1341834988686, "label" : "paul", "responseCode" : "404", "value" : 15, "success" : "true"}

5. { "timeStamp" : 1341834988266, "label" : "paul", "responseCode" : "404", "value" : 99, "success" : "false"}
26
demandé sur Neil Lunn 2012-07-10 21:48:50

1 réponses

OK, donc la solution est de spécifier une clé agrégée pour la valeur _id. Ceci est documenté ici comme:

vous pouvez spécifier un seul champ à partir des documents dans le pipeline, une valeur calculée précédemment, ou une clé agrégée composée de plusieurs champs entrants.

mais il ne définit pas réellement le format d'une clé agrégée. Lire la documentation précédente ici j'ai vu que la précédente collection.méthode du groupe de pourrait prendre plusieurs champs et que la même structure est utilisée dans le nouveau cadre.

ainsi, pour grouper plusieurs champs vous pouvez utiliser _id : { success:'$success', responseCode:'$responseCode', label:'$label'}

Comme dans:

resultsCollection.aggregate(
{ $match : { testid : testid} },
{ $skip : alreadyRead },
{ $project : {
        timeStamp : 1 ,
        label : 1,
        responseCode : 1 ,
        value : 1,
        success : 1
    }},
{ $group : {
        _id :  { success:'$success', responseCode:'$responseCode', label:'$label'},
        max_timeStamp : { $timeStamp : 1 },
        count_responseCode : { $sum : 1 },
        avg_value : { $sum : "$value" },
        count_success : { $sum : 1 }
    }}
);
37
répondu Oliver Lloyd 2013-03-10 20:03:37