2010-11-23 17 views
22

Estoy buscando un ejemplo de cómo implementar y usar Map-Reduce dentro del Cliente RavenDB .NET.RavenDB Map-Reduce Ejemplo usando .NET Client

Me gustaría aplicarlo a un escenario específico: generar recuentos de visitantes únicos y totales.

Un documento de muestra que se almacena dentro de RavenDB:

public class StatisticsEntry 
{ 
    public string Id { get; set; } 
    public string UserId { get; set; } 
} 

puedo encontrar la manera de crear un índice estándar utilizando Map, pero estoy perdido en cuanto a cómo utilizar realmente la función de reducir y luego recupera los resultados.

Desafortunadamente, el example provided on the RavenDB Site no explica qué está pasando para que yo pueda entender cómo usarlo a través de la API .NET, y las muestras no parecen implementar esto en absoluto usando la API de .NET.

+0

¿Qué quiere lograr? ¿Quieres usar la hora de la fecha de alguna manera? (Por día, por mes, por año un poco las cosas?) –

+0

No en este momento. Es posible que tenga índices adicionales más adelante usando este campo. Por el momento, lo eliminaré de la clase para simplificarlo. En cuanto a "Querer lograr", quiero generar estadísticas que muestren a) el recuento total de StatisticsEntry yb) los usuarios únicos. –

+0

De acuerdo, porque necesitaría un mapa/reducir el índice por 'agrupamiento' en ese tipo de escenario; la respuesta aparece en un momento –

Respuesta

38

Un índice de reducción de mapa es solo otra forma de decir "Quiero hacer un grupo por", solo el grupo de es pre -definido desde el principio y RavenDB lo procesará de manera eficiente en segundo plano, por lo que en el momento de la consulta está buscando un resultado precalculado.

Considere lo siguiente como una respuesta como un grupo ordinario por (para usuarios únicos)

var results = from doc in docs 
group doc by doc.UserId into g 
select new 
{ 
     g.UserId, 
     g.Count() 
} 

Haciendo caso omiso de los contenidos reales de la matriz creada, podemos obtener los resultados totales pidiendo

results.Length 

como era de esperar.

En RavenDB, que divide a cabo esta función en un mapa y la escala de reducción, y se termina con

public class UniqueVisitorsResult 
{ 
    public string UserId { get; set; } 
    public int Count { get; set; } 
} 

public class UniqueVisitorsIndex : AbstractIndexCreationTask<StatisticsEntry, UniqueVisitorsResult> 
{ 
    public UniqueVisitorsIndex() 
    { 
     Map = docs=> from doc in docs 
         select new 
         { 
          UserId = doc.UserId, 
          Count = 1 
         }; 
     Reduce = results => from result in results 
         group result by result.UserId into g 
         select new 
         { 
          UserId = g.Key, 
          Count = g.Sum(x=>x.Count) 
         }; 
    } 
} 

En esencia, esto es lo mismo que el anterior - pero has lo convirtió en una MapReduce función ;-)

session.Query<StatisticEntry, UniqueVisitorsIndex>().Count(); 

le dará el número total de visitantes únicos, asumiendo conde se ha implementado correctamente en el proveedor de LINQ (IIRC creo que tiene)

el total número de entradas es simplemente

session.Query<StatisticEntry>().Count(); 

Como era de esperar (No hay ningún mapa/reducir requerido)

Nota: este índice también se puede utilizar para ver el número de golpes por un usuario específico, como el conde se calcula en el índice, si no le importa el conteo, suelte esa parte de MapReduce y haga

public class UniqueVisitorsIndex : AbstractIndexCreationTask<StatisticsEntry> 
{ 
    public UniqueVisitorsIndex() 
    { 
     Map = docs=> from doc in docs 
        select new 
        { 
         UserId = doc.UserId 
        }; 
     Reduce = results => from result in results 
        group result by result.UserId into g 
        select new 
        { 
         UserId = g.Key 
        }; 
    } 
} 
+0

Impresionante. Gracias por la explicación. –

+0

En el primer ejemplo, usted proporciona 'Count = g.Sum (x => x.Count)' - esto me da un error de compilación cuando 'x' es de tipo' StatisticsEntry' - ¿De dónde se supone que proviene? –

+1

Ah, defina una forma de salida, permítame modificar el ejemplo :) –

18

Aquí es cómo se puede construir un índice de visitantes únicos:

public class Statistics_UniqueVisitors : AbstractIndexCreationTask<StatisticsEntry> 
{ 
    public Statistics_UniqueVisitors() 
    { 
     Map = entries => from entry in entries 
         select new { entry.UserId, Count = 1 }; 
     Reduce = results => from result in results 
          group result by result.UserId into g 
          select new { UserId = g.Key, Count = g.Sum(x=>x.Count) }; 
    } 
} 

continuación, se puede consultar esta usando:

var numberOfUniqueVisitors = s.Query<StatisticEntry, Statistics_UniqueVisitors>().Count(); 

para el recuento total de visitantes, se puede utilizar:

var numberOfVisitors = s.Query<StatisticEntry>().Count(); 
Cuestiones relacionadas