sql >> Base de Datos >  >> NoSQL >> MongoDB

cómo calcular el conteo y el conteo único en dos campos en la función de reducción de mongo

De hecho, puede pasar un objeto arbitrario en el segundo parámetro de la llamada de emisión. Eso significa que puede aprovechar esto y almacenar el ID de usuario en él. Por ejemplo, su función de mapa puede verse así:

var mapFunc = function() {
  if (this.track_redirect) {
    var tempDoc = {};
    tempDoc[this.track_userid] = 1;

    emit(this.track_redirect, {
      users_clicked: tempDoc,
      total_clicks: 1
    });
  }
};

Y su función de reducción podría verse así:

var reduceFunc = function(key, values) {
  var summary = {
    users_clicked: {},
    total_clicks: 0
  };

  values.forEach(function (doc) {
    summary.total_clicks += doc.total_clicks;
    // Merge the properties of 2 objects together
    // (and these are actually the userids)
    Object.extend(summary.users_clicked, doc.users_clicked);
  });

  return summary;
};

La propiedad users_clicked del objeto de resumen básicamente almacena la identificación de cada usuario como una propiedad (ya que no puede tener propiedades duplicadas, puede garantizar que almacenará usuarios únicos). También tenga en cuenta que debe tener cuidado con el hecho de que algunos de los valores pasados ​​a la función de reducción pueden ser el resultado de una reducción anterior y el código de ejemplo anterior lo tiene en cuenta. Puede encontrar más información sobre dicho comportamiento en los documentos aquí .

Para obtener el conteo único, puede pasar la función del finalizador que se llama cuando se completa la fase de reducción:

var finalFunc = function(key, value) {
  // Counts the keys of an object. Taken from:
  // http://stackoverflow.com/questions/18912/how-to-find-keys-of-a-hash
  var countKeys = function(obj) {
    var count = 0;

    for(var i in obj) {
      if (obj.hasOwnProperty(i))
      {
        count++;
      }
    }

    return count;
  };

  return {
    redirect: key,
    total_clicks: value.total_clicks,
    unique_clicks: countKeys(value.users_clicked)
  };
};

Finalmente, puede ejecutar el trabajo de reducción de mapas de esta manera (modifique el atributo out para que se ajuste a sus necesidades):

db.users.mapReduce(mapFunc, reduceFunc, { finalize: finalFunc, out: { inline: 1 }});