2012-07-10 13 views
26

me gustaría utilizar Marco agregación de MongoDB para ejecutar lo que en SQL se vería un poco como:Mongodb Aggregation Framework | ¿Grupo sobre valores múltiples?

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

El estado docs:

puede especificar un campo simple de los documentos en la tubería , un valor calculado previamente, o una clave agregada compuesta de varios campos entrantes.

¿Pero no está claro qué es realmente una 'clave agregada hecha de varios campos entrantes'?

Mi conjunto de datos es un poco como esto:

[{ "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"}] 

Mi consulta es el siguiente:

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 : { 
      ? 
     }} 
); 

Mi instinto fue tratar de canalizar los resultados a través de un segundo grupo, te conozco puede hacer esto pero no funcionará porque el primer grupo ya reduce demasiado el conjunto de datos y se pierde el nivel de detalle requerido.

Lo que quiero hacer es agrupar usando label, responseCode y success y obtener la suma del valor del resultado. Debe tener un aspecto un poco como:

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 

Donde hay cinco grupos:

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"} 

Respuesta

37

bien, así que la solución es especificar una clave para el valor agregado _id. Esto está documentado here como:

puede especificar un campo simple de los documentos en la tubería, un valor calculado previamente, o una tecla de agregado que se compone de varios campos de entrada.

Pero en realidad no define el formato para una clave agregada. Leyendo la documentación anterior here Vi que el método collection.group anterior podría tomar múltiples campos y que la misma estructura se usa en el nuevo framework.

Por lo tanto, al grupo a través de múltiples campos se puede utilizar _id : { success:'$success', responseCode:'$responseCode', label:'$label'}

Como en:

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

cuál es el propósito de su proyecto $? es el documento original mucho más grande? también omitir no tiene mucho sentido sin un género antes. y si necesita avg_value ¿por qué no usa $ avg? si quieres suma, ¿por qué no lo llamas sum_value? También count_success y count_responseCode van a ser lo mismo, no estoy seguro de por qué necesita ambos. –

+9

Nota: A partir de 2.2.0-rc1, se han realizado pequeños cambios en la agrupación por varios campos: _id: {success: 1, responseCode: 1, label: 1} se convertiría en _id: {success: "$ success", responseCode: "$ responseCode", etiqueta: "$ label"}. https://groups.google.com/forum/?fromgroups#!topic/mongodb-user/1cYch580h0w – Richard

+1

respuesta corregida de acuerdo con @Richard. –

Cuestiones relacionadas