2010-05-12 21 views
20

Necesito algo un poco más complejo que los ejemplos en los documentos de MongoDB y parece que no soy capaz de entenderlo.Usando el mapa de MongoDB/reducir a "agrupar por" dos campos

Decir que tengo una colección de objetos de la forma {date: "2010-10-10", type: "EVENT_TYPE_1", user_id: 123, ...}

Ahora quiero conseguir algo similar a un grupo de SQL POR consulta, agrupando tanto sobre la fecha y el tipo. Es decir, quiero el número de eventos de cada tipo en cada día. Además, me gustaría que sea único por user_id, es decir. si un usuario tiene más eventos en el mismo día, cuente solo una vez.

Estoy tratando de hacer esto con map/reduce.

debo hacer

db.logs.mapReduce( 
    function() { 
     emit(this.type, 1); 
    }, 
    function(k, vals) { 
     var total = 0; 
     for (var i = 0; i < vals.length; i++) 
      total += vals[i]; 
     return total; 
    } 
) 

la que muy bien grupos según el tipo, pero ahora, ¿cómo puedo grupo por fecha, al mismo tiempo? Parece que la clave en emitir() no puede ser una matriz (pensé en hacer emit([this.date, this.type], 1)). Además, ¿cómo puedo garantizar la exclusividad por usuario?

Estoy empezando con MongoDB y sigo teniendo problemas para comprender los conceptos básicos. Además, no hay mucha documentación disponible por ahí. Se agradece cualquier ayuda de usuarios más experimentados. ¡Gracias!

+0

couchdb puede hacer matrices como llaves, simplemente diciendo ' – dominic

Respuesta

19

Encontré una muy buena solución en el libro de cocina MongoDB (no conocía este recurso antes).

http://cookbook.mongodb.org/patterns/unique_items_map_reduce/

Básicamente, para agrupar por varias claves, se utiliza un diccionario, no una lista (como he tratado). Además, para obtener resultados únicos, debe realizar dos pases de asignación/reducción.

+3

El enlace no funciona. Cualquiera que esté interesado en agrupar/emitir en unos pocos campos puede usar la siguiente estructura: emitir ({fecha: this.date, tipo: this.type}, 1) –