Пример RavenDB Map-Reduce с использованием .NET Client - PullRequest
22 голосов
/ 23 ноября 2010

Я ищу пример того, как внедрить и использовать Map-Reduce в RavenDB .NET Client.

Я бы хотел применить его к определенному сценарию: генерация уникальных и общих посетителей.

Пример документа, который будет храниться в RavenDB:

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

Я могу выяснить, как создать стандартный индекс с помощью Map, но я заблудился относительно того, как на самом деле использовать функцию Reduce, а затем получить результаты.

К сожалению, пример , представленный на сайте RavenDB , не объясняет, что происходит, поэтому я не могу понять, как его использовать через .NET API, и примеры, кажется, не реализуют это вообще используя .NET API.

Ответы [ 2 ]

38 голосов
/ 23 ноября 2010

Индекс уменьшения карты - это просто еще один способ сказать «Я хочу сделать группу по», заранее определена только группа по, и RavenDB будет эффективно обрабатывать ее в фоновом режиме, поэтому во время запроса выищем предварительно вычисленный результат.

Рассмотрим следующее как ответ как обычную группу (для уникальных пользователей)

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

Игнорируя фактическое содержимое созданного массива, мыможно получить итоговые результаты, запросив

 results.Length

, как и следовало ожидать.

В RavenDB вы разделили эту функцию на Map и Reduce и в итоге получили

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) 
                        };
    }
}

По сути, это то же самое, что и выше - но вы превратили его в функцию MapReduce; -)

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

Даст вам общее количество уникальных посетителей.при условии, что Count был правильно реализован в поставщике LINQ (iirc, я думаю, что он есть)

Общее количество записей просто

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

Как и следовало ожидать (без карты / уменьшениятребуется)

Примечание: этот индексex также может использоваться для просмотра количества обращений конкретного пользователя, так как Count рассчитывается в индексе, если вы не заботитесь о подсчете, отбросьте эту часть MapReduce и выполните

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
                    };
    }
}
18 голосов
/ 23 ноября 2010

Вот как вы можете построить индекс для уникальных посетителей:

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) };
    }
}

Вы можете запросить это, используя:

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

Для общего количества посетителей вы можете использовать:

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