2010-06-09 21 views
12

Primera vez Mapa/Reducir usuario aquí, y utilizando MongoDB. Tengo una gran cantidad de datos de visitas a la página que me gustaría tener un poco de sentido mediante el uso de Map/Reduce. Debajo está básicamente lo que quiero hacer, pero como principiante total, un Mapa/Reducir, ¡creo que está por encima de mi conocimiento!Mongo Map Reducir por primera vez

  1. Revise todas las páginas con visitas en los últimos 30 días, y donde external = true.
  2. Luego, para cada página, encontrará todas las visitas
  3. Grupo todas las visitas de ubicación de referencia
  4. Para cada lugar de referencia, calcular cuántos luego fue a visitar una página que tiene un cierto "tipo" y también tiene una cierta palabra en las "etiquetas".

La base de datos y recogida están organizadas como documento

$mongo->dbname->visits 

Una muestra es:

{"url": "www.example.com", "type": "a", "refer": {"external": true, "domain": "twitter.com", "url": "http://www.twitter.com/page"}, "page": "1235", "user": "1232", "time": 1234567890} 

Y entonces quiero encontrar documentos de tipo B con una determinada etiqueta.

{"url": "www.example.com", "type": "b", "page": "745", "user": "1232", "time": 1234567890, "tags": {"a", "b", "c"}} 

Estoy usando la extensión normal de Mongo PHP si eso tiene un impacto.

+1

¿Qué estructura de base de datos tiene usted? ¿Cómo se organizan sus colecciones y documentos? –

+0

Agregado a la publicación anterior. ¿Que ayuda? – James

+0

OK, su documento de muestra no incluye un campo de "referencia" y un campo "externo" o "etiquetas". Lo que sugiere es realmente complicado, por lo que probablemente necesite mostrarnos más de un documento. Y probablemente deba mostrarlo con todos los detalles. –

Respuesta

16

Ok, he encontrado algo que creo que puede hacer lo que quiera. Tenga en cuenta que esto puede no funcionar exactamente ya que no estoy 100% seguro de su esquema (teniendo en cuenta que sus ejemplos muestran refer disponible en tipo a, pero no b (no estoy seguro si eso es una omisión, o si lo que desea es Ver por árbitro) ... de todos modos, esto es lo que he llegado con:

La función de mapa:

function() { 
    var obj = { 
     "types": {}, 
     "tags": {}, 
    } 
    obj.types[this.type] = 1; 
    if (this.tags) { 
     for (var tag in this.tags) { 
      obj.tags[this.tags[tag]] = 1; 
     } 
    } 
    emit(this.refer.url, obj); 
} 

El reducen la función:

function(key, values) { 
    var obj = { 
     "types": {}, 
     "tags": {}, 
    } 
    for (var i = 0; i < values.length; i++) { 
     for (var type in values[i].types) { 
      if (!type in obj.types) { 
       obj.types[type] = 0; 
      } 
      obj.types[type] += values[i].types[type]; 
     } 
     for (var tag in values[i].tags) { 
      if (!tag in obj.tags) { 
       obj.tags[tag] = 0; 
      } 
      obj.tags[tag] += values[i].tags[tag]; 
     } 
    } 
    return obj; 
} 

Así que, básicamente, cómo funciona es esto. La función de mapa utiliza una clave de refer.url (lo que adiviné en función de su desc ription). Por lo tanto, el resultado final se verá como una matriz con _id igual a refer.url (Se agrupa según url). Luego crea un objeto que tiene dos objetos debajo (tipos y etiquetas). La razón para el objeto es para que map y reduce puedan emitir el mismo objeto de formato. Aparte de eso, creo que debería ser relativamente explica por sí mismo (Si usted no entiende, puedo tratar de explicar más) ...

Así que vamos a implementar esto en PHP (suponiendo que $map y $reduce son cadenas con lo anterior contenida con ellos por concisión):

$mapFunc = new MongoCode($map); 
$reduceFunc = new MongoCode($reduce); 
$query = array(
    'time' => array('$gte' => time() - (60*60*60*24*30)), 
    'refer.external' => true 
); 
$collection = 'visits'; 
$command = array(
    'mapreduce' => $collection, 
    'map' => $mapFunc, 
    'reduce' => $reduceFunc, 
    'query' => $query, 
); 

$statsInfo = $db->command($command); 

$statsCollection = $db->selectCollection($sales['result']); 

$stats = $statsCollection->find(); 

foreach ($stats as $stat) { 
    echo $stats['_id'] .' Visited '; 
    foreach ($stats['value']['types'] as $type => $times) { 
     echo "Type $type $times Times, "; 
    } 
    foreach ($stats['value']['tags'] as $tag => $times) { 
     echo "Tag $tag $times Times, "; 
    } 
    echo "\n"; 
} 

Nota, no he probado esto. Esto es justo lo que he llegado con base en mi comprensión de su esquema, y ​​desde mi comprensión de Mongo y su aplicación Map-Reduce ...

+0

$ statsCollection = $ db-> selectCollection ($ sales ['result']); $ sales? – Tobias

Cuestiones relacionadas