2011-09-06 3 views
0

J'ai une carte à réduire comme ceci:carte MongoDB réduire la production de différents résultat à db.collection.find()

Carte:

function() { 
     emit(this.username, {sent:this.sent, received:this.received}); 
} 

réduire:

function(key, values) {                                                   
    var result = {sent: 0, received: 0, entries:0}; 

    values.forEach(function (value) { 
     result.sent += value.sent; 
     result.received += value.received; 
     result.entries += 1; 
    }); 

    return result; 
} 

J'ai été surveiller la quantité d'entrées traitées dans la carte de résultat, comme vous pouvez le voir. J'ai constaté que je reçois beaucoup moins d'enregistrements consultés que je ne le devrais.

Pour mon jeu de données particulier, la sortie est comme ceci:

[{u'_id ': u'1743', u'value ': {u'received': 1.406.545,0, u'sent ': 26251138.0, u'entries': 316,0}}]

Comme je suis en la carte réduire avec une option de requête, en spécifiant un nom d'utilisateur et une plage de dates.

Si j'effectue la même requête en utilisant db.collection.find() comme suit, le nombre est différent:

> db.entire_database.find({username: '1743', time : { $lte: ISODate('2011-08-12 12:40:00'), $gte: ISODate('2011-08-12 08:40:00') }}).count()       
1915 

La carte complète réduire requête est la suivante:

db.entire_database.mapReduce(m, r, {out: 'myoutput', query: { username: '1743', time : { $lte: ISODate('2011-08-12 12:40:00'), $gte: ISODate('2011-08-12 08:40:00') } } }) 

Donc, fondamentalement, , Je ne sais pas pourquoi le compte est si radicalement différent? Pourquoi la find() me donne-t-elle 1915, mais la carte est réduite à 316?

Répondre

4

Votre fonction map doit émettre un objet ayant la même forme que la fonction reduce (par exemple, un champ entries doit être défini sur 1). Vous pouvez lire plus à ce sujet here. En principe, les valeurs transmises à la fonction reduce ne sont pas nécessairement les sorties brutes émises par map. Plutôt que d'être appelée une fois, la fonction reduce est appelée plusieurs fois sur des 'groupes' de valeurs produites par map, les résultats sont ensuite combinés à nouveau en étant passés à un autre appel de la fonction reduce. C'est ce qui rend MapReduce horizontalement évolutive, parce que tout groupe de valeurs émises peut être affermé à un serveur dans un ordre quelconque avant d'être combinés plus tard.

donc je restructurer vos fonctions un peu comme ceci:

Carte:

function() { 
    emit(this.username, {sent:this.sent, received:this.received, entries : 1}); 
} 

réduire:

function(key, values) {                                                   
    var result = {sent: 0, received: 0, entries:0}; 

    values.forEach(function (value) { 
     result.sent += value.sent; 
     result.received += value.received; 
     result.entries += value.entries; 
    }); 

    return result; 
} 
+0

Bien sûr! Merci tas Russell. –

+0

Pas de problème! Heureux de vous aider. – Russell

Questions connexes