RavenDB Map-Reduce Ejemplo usando.NET Client
mapreduce (2)
Estoy buscando un ejemplo de cómo implementar y usar Map-Reduce dentro del Cliente RavenDB .NET.
Me gustaría aplicarlo a un escenario específico: generar conteos únicos y totales de visitantes.
Un documento de muestra que se almacenaría dentro de RavenDB:
public class StatisticsEntry
{
public string Id { get; set; }
public string UserId { get; set; }
}
Puedo descubrir cómo crear un índice estándar usando Map, pero no entiendo cómo usar realmente la función Reducir y luego recuperar los resultados.
Desafortunadamente, el ejemplo proporcionado en el sitio RavenDB no explica qué está pasando, de modo que puedo entender cómo usarlo a través de la API .NET, y las muestras no parecen implementar esto en absoluto utilizando la API .NET.
Aquí es cómo puede crear un índice para 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) };
}
}
Luego puedes consultar esto usando:
var numberOfUniqueVisitors = s.Query<StatisticEntry, Statistics_UniqueVisitors>().Count();
Para el recuento total de visitantes, puede utilizar:
var numberOfVisitors = s.Query<StatisticEntry>().Count();
Un índice de reducción de mapa es solo otra forma de decir "Quiero hacer un grupo por", solo el grupo está predefinido por adelantado 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()
}
Ignorando el contenido real de la matriz creada, podemos obtener los resultados totales solicitando
results.Length
como es de esperar
En RavenDB, divides esta función en un Mapa y un Reducir, y terminas 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 lo anterior, pero lo has convertido en una función MapReduce ;-)
session.Query<StatisticEntry, UniqueVisitorsIndex>().Count();
Le dará el número total de visitantes únicos, suponiendo que Count se haya implementado correctamente en el proveedor de LINQ (creo que sí lo ha hecho)
El número total de entradas es simplemente
session.Query<StatisticEntry>().Count();
Como era de esperar (No se requiere mapa / reducción)
Nota: este índice también se puede usar para ver el número de visitas de un usuario específico, ya que el conteo 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
};
}
}