MapReduce en PyMongo

Mi colección de Mongo: Impressions tiene documentos en el siguiente formato: –

  { _uid: 10, "impressions": [ { "pos": 6, "id": 123, "service": "furniture" }, { "pos": 0, "id": 128, "service": "electronics" }, { "pos": 2, "id": 127, "service": "furniture" }, { "pos": 2, "id": 125, "service": "electronics" }, { "pos": 10, "id": 124, "service": "electronics" } ] }, { _uid: 11, "impressions": [ { "pos": 1, "id": 124, "service": "furniture" }, { "pos": 10, "id": 124, "service": "electronics" }, { "pos": 1, "id": 123, "service": "furniture" }, { "pos": 21, "id": 122, "service": "furniture" }, { "pos": 3, "id": 125, "service": "electronics" }, { "pos": 10, "id": 121, "service": "electronics" } ] }, . . . . . 

Cada uno de los documentos de la colección tiene "impressions" clave de "impressions" que es una matriz de diccionarios. En cada diccionario, "id" es el id de la entidad, "service" es el tipo de servicio y "pos" es la posición del elemento en los resultados de la página de búsqueda. Mi objective es averiguar el número de impresiones para cada "id" en cada categoría. Así que para los datos anteriores para "service" == "furniture" , quiero tener esto como resultados de mi agregación: –

 [ {"id": 123,"impressions_count":2}, {"id": 127,"impressions_count":1}, {"id": 124,"impressions_count":1}, {"id": 122,"impressions_count":1} ] 

Intenté agregar el “id” usando MAPREDUCE a través de la siguiente función en un script de python

 def fetch_impressions(): try: imp_collection = get_mongo_connection('Impressions') map = Code(""" function(){ for( x in this.impressions){ var flat_id = x['id']; var service_type = x['service'] emit(parseInt(flat_id),1); } }; """) """) reduce = Code(""" function(a,b){ return Array.sum(b); }; """) results = imp_collection.map_reduce(map, reduce, 'aggregation_result') return results except Exception as e: raise Exception(e) 

Pero estoy obteniendo los resultados como Ninguno, probablemente debido a la función defectuosa del mapa. ¡Soy nuevo en Javascript y Mongo por favor ayuda!

Puede utilizar el marco de agregación

 import pymongo conn = pymongo.MongoClient() db = conn.test col = db.collection for doc in col.aggregate([{'$unwind': '$impressions'}, {'$match': {'impressions.service': 'furniture'}}, {'$group': {'_id': '$impressions.id', 'impressions_count': {'$sum': 1}}}, ]): print(doc) 

O más eficientemente usando los operadores $map y $setDifference .

 col.aggregate([ { "$project": { "impressions": {"$setDifference": [{ "$map": { "input": "$impressions", "as": "imp", "in": { "$cond": { "if": { "$eq": [ "$$imp.service", "furniture" ] }, "then": "$$imp.id", "else": 0 }}}}, [0]]}}}, { "$unwind": "$impressions" }, { "$group": { "_id": "$impressions", "impressions_count": { "$sum": 1 }}} ]) 

Cuyos rendimientos:

 {'_id': 122.0, 'impressions_count': 1} {'_id': 124.0, 'impressions_count': 1} {'_id': 127.0, 'impressions_count': 1} {'_id': 123.0, 'impressions_count': 2}