RavenDB Map-Reduce Example using .NET Client

╄→гoц情女王★ 提交于 2019-11-29 20:38:19

A map reduce index is just another way of saying "I want to do a group by", only the group by is pre-defined up front and RavenDB will process it in an efficient manner in the background so at query time you are looking up a pre-calculated result.

Consider the following as an answer as an ordinary group by (for unique users)

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

Ignoring the actual contents of the created array, we can get the total results by asking for

 results.Length

as you'd expect.

In RavenDB, you split out this function into a Map and a Reduce, and you end up with

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

In essence, this is the same as the above - but you've turned it into a MapReduce function ;-)

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

Will give you the total number of unique visitors, assuming Count has been implemented properly in the LINQ provider (iirc I think it has)

The total number of entries is simply

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

As you'd expect (No map/reduce required)

Note: this index can also be used to see the number of hits by a specific user, as the Count is being calculated in the index, if you don't care about the count then drop that part of the MapReduce and do

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
                    };
    }
}
Ayende Rahien

Here is how you can build an index for unique visitors:

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

You can then query this using:

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

For total count of visitors, you can use:

var numberOfVisitors = s.Query<StatisticEntry>().Count();
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!