2011-03-09 2 views
3

J'ai une base de données CouchDB avec une vue dont les valeurs sont des nombres appariés de la forme [x, y]. Pour les documents avec la même clé, j'ai besoin (simultanément) de calculer le minimum de x et le maximum de y. La base de données avec laquelle je travaille contient environ 50000 documents. Construire la vue prend plusieurs heures, ce qui semble un peu excessif. (Les clés sont elles-mêmes des tableaux de trois longueurs.) Je montre la carte et réduit les fonctions ci-dessous, mais la question fondamentale est: comment puis-je accélérer ce processus?plus rapide min et max de différents composants de la baie avec CouchDb map/reduce?

Notez que les fonctions intégrées ne fonctionneront pas car les valeurs doivent être des nombres, pas des tableaux de longueur. Il est possible que je puisse faire deux vues différentes (une pour min (x) et une pour max (y)), mais je ne vois pas comment les combiner pour obtenir les deux résultats simultanément.

Ma fonction actuelle carte ressemble fondamentalement

function(doc) { 
    emit ([doc.a, doc.b, doc.c], [doc.x, doc.y]) 
} 

et ma fonction reduce ressemble

function(keys, values) { 
    var x = null; 
    var y = null; 
    for (i = 0; i < values.length; i++) { 
    if (values[i][0] == null) break; 
    if (values[i][1] == null) break; 
    if (x == null) x = values[i][0]; 
    if (y == null) y = values[i][1]; 
    if (values[i][0] < x) x = values[i][0]; 
    if (values[i][1] > y) y = values[i][1]; 
    } 
    emit([x, y]); 
} 

Répondre

1

Ce avéré être une combinaison de deux facteurs. On est évident dans le code posté ci-dessus, où utilise "emit" quand il devrait utiliser "return".

L'autre facteur est moins évident et n'a été trouvé qu'en créant une version plus petite de la base de données et en enregistrant les étapes dans la fonction de réduction. Bien que les entrées dans "valeurs" étaient censées être des entiers, ils étaient traités par CouchDB comme des chaînes de caractères. L'utilisation de la fonction parseInt a corrigé ce problème. Après ces deux corrections, la construction complète de la vue réduite prenait environ cinq minutes, de sorte que le problème de vitesse s'est évaporé.

2

Juste deux autres notes. Utiliser Math.max() et Math.min() devrait être un peu plus rapide.

function(keys, values) { 
    var x = -Infinity, 
     y = Infinity; 
    for (var i = 0, v; v = values[i]; i++) { 
    x = Math.max(x, v[0]); 
    y = Math.min(y, v[1]); 
    } 
    return [x, y]; 
} 

Et si CouchDB traite les valeurs sous forme de chaînes, il est parce que vous les stocker sous forme de chaînes dans le document.

Espérons que ça aide.

+0

Je n'avais pas essayé Math.max parce que je ne savais pas comment il traitait null. (Je travaille beaucoup dans R, où l'équivalent le plus proche de null est NA, qui absorbe tous les nombres dans les opérations arithmétiques.) Exécuter un test, cependant, confirme que Math.max ignore les valeurs nulles, et fonctionne donc ici. –

+0

Pas exactement. Math.max n'ignore pas null, il le traite comme 0. Par exemple: "Math.max (null, 1) == 1", "Math.max (null, -1) == 0". Tous les tests suivants sont vrais: "-1 -1" et "null> = 0". C'est pourquoi j'ai utilisé -Infinity comme valeur de départ. –