Exemplo de Ravendb Map-Reduce usando o .NET Client
Pergunta
Estou procurando um exemplo de como implementar e usar o REDUCO MAP no Ravendb .NET Client.
Eu gostaria de aplicá -lo a um cenário específico: gerando contagens exclusivas e totais de visitantes.
Um exemplo de documento que seria armazenado no Ravendb:
public class StatisticsEntry
{
public string Id { get; set; }
public string UserId { get; set; }
}
Posso descobrir como criar um índice padrão usando o mapa, mas estou perdido sobre como realmente usar a função Reduzir e recuperar os resultados.
Infelizmente, o Exemplo fornecido no site de Ravendb Não explica o que está acontecendo para que eu possa entender como usá -lo através da API .NET, e as amostras não parecem implementar isso usando a API .NET.
Solução
Um índice de redução do mapa é apenas outra maneira de dizer "eu quero fazer um grupo por", apenas o grupo é predefinido na frente e Ravendb o processará de maneira eficiente em segundo plano um resultado pré-calculado.
Considere o seguinte como uma resposta como um grupo comum por (para usuários únicos)
var results = from doc in docs
group doc by doc.UserId into g
select new
{
g.UserId,
g.Count()
}
Ignorando o conteúdo real da matriz criada, podemos obter os resultados totais pedindo
results.Length
Como você esperaria.
Em Ravendb, você dividiu essa função em um mapa e reduz, e acaba com
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)
};
}
}
Em essência, é o mesmo que o acima - mas você o transformou em uma função MapReduce ;-)
session.Query<StatisticEntry, UniqueVisitorsIndex>().Count();
Dará a você o número total de visitantes únicos, assumindo que a contagem tenha sido implementada corretamente no provedor LINQ (IIRC, acho que sim)
O número total de entradas é simplesmente
session.Query<StatisticEntry>().Count();
Como seria de esperar (sem mapa/redução necessária)
Nota: Este índice também pode ser usado para ver o número de acertos por um usuário específico, pois a contagem está sendo calculada no índice, se você não se importa com a contagem, solte essa parte do MapReduce e faça
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
};
}
}
Outras dicas
Aqui está como você pode criar um í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) };
}
}
Você pode então consultar isso usando:
var numberOfUniqueVisitors = s.Query<StatisticEntry, Statistics_UniqueVisitors>().Count();
Para contagem total de visitantes, você pode usar:
var numberOfVisitors = s.Query<StatisticEntry>().Count();