22

我正在寻找如何在 RavenDB .NET 客户端中实现和使用 Map-Reduce 的示例。

我想将其应用于特定场景:生成唯一的访客总数和总访客数。

将存储在 RavenDB 中的示例文档:

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

我可以弄清楚如何使用 Map 创建标准索引,但我不知道如何实际使用 Reduce 函数,然后检索结果。

不幸的是,RavenDB 站点上提供的示例没有解释发生了什么,因此我可以理解如何通过 .NET API 使用它,并且示例似乎根本没有使用 .NET API 实现这一点。

4

2 回答 2

38

map reduce index 只是另一种表达“我想做一个 group by”的方式,只有 group by 是预先定义好的,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();

如您所料(不需要 map/reduce)

注意:此索引也可用于查看特定用户的点击次数,因为 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
                    };
    }
}
于 2010-11-23T10:44:50.697 回答
18

以下是为唯一身份访问者建立索引的方法:

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();
于 2010-11-23T10:39:33.097 回答