RavenDB Map-Reducir Ejemplo utilizando .NET Client
Pregunta
Busco un ejemplo de cómo implementar y utilizar Map-Reducir dentro del RavenDB .NET cliente.
Me gustaría aplicarlo a un escenario específico: la generación de los 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; }
}
Me puede 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 recuperar los resultados.
Por desgracia, el ejemplo proporcionada en el sitio RavenDB no explica lo que está pasando por lo que pueda entender cómo usarlo a través de la API .NET, y no parecen las muestras para implementar esto en absoluto el uso de la API .NET.
Solución
Un mapa reducir el índice es más que otra forma de decir "yo quiero hacer un grupo por", sólo el grupo de está predefinida en la delantera y RavenDB lo procesará de manera eficiente en el fondo para que en tiempo de consulta se están buscando un resultado calculado previamente.
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 una Reducir, y 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 te has convertido en una función MapReduce; -)
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 número total de entradas es simplemente
session.Query<StatisticEntry>().Count();
Como era de esperar (n map / reduce requiere)
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 se preocupan por el recuento a continuación, colocar la parte de la MapReduce y hacer
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
};
}
}
Otros consejos
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) };
}
}
A continuación, 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();