문제

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 and total visitor counts.

A sample document that would be stored within RavenDB:

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

I can figure out how to create a standard index using Map, but I'm lost as to how to actually use the Reduce function, and then retrieve the results.

Unfortunately, the example provided on the RavenDB Site doesn't explain what's going on so that I can understand how to use it via the .NET API, and the samples don't seem to implement this at all using the .NET API.

도움이 되었습니까?

해결책

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

다른 팁

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();
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top