RavenDB Map-Reduce Example using .NET Client

前端 未结 2 719
闹比i
闹比i 2020-12-23 10:14

I\'m looking for an example of how to implement and use Map-Reduce within the RavenDB .NET Client.

I\'d like to apply it to a specific scenario: generating unique a

相关标签:
2条回答
  • 2020-12-23 10:54

    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
                        };
        }
    }
    
    0 讨论(0)
  • 2020-12-23 11:01

    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();
    
    0 讨论(0)
提交回复
热议问题