我正在使用 RavenDB 来存储一系列事件。这些事件有一个我用来按天分组的日期 (DateTime.Date)。我试图按小时添加一些统计数据,但我似乎无法找到一种干净的方法。

简单的方法:

public class DailyStats : AbstractIndexCreationTask<Incident, DateStat>
{
    public DailyStats()
    {
        Map = docs => from doc in docs
                      select new
                                 {
                                     doc.OccuredOn,
                                     Hour0 = doc.OccuredOn.Hour == 0 ? 1 : 0
                                     Hour1 = doc.OccuredOn.Hour == 1 ? 1 : 0
                                     //....
                                 };

        Reduce = mapped => from m in mapped
                           group m by new { m.Date.Date }
                           into g
                           select new
                                      {
                                          g.Key.Date,
                                          Hour0 = g.Sum(x => x.Hour0),
                                          Hour1 = g.Sum(x => x.Hour1)
                                          //....
                                      }
    }
}

但这是可怕的重复。相反,我正在尝试使用字典:
public class DailyStats : AbstractIndexCreationTask<Incident, DateStat>
{
    public DailyStats()
    {
        Map = docs => from doc in docs
                      select new
                                 {
                                     doc.OccuredOn,
                                     IncidentsByHour = Enumerable.Range(0, 24).ToDictionary(h => h, h => doc.IncidentDate.Hour == h ? 1 : 0),
                                 };

        Reduce = mapped => from m in mapped
                           group m by new { m.Date.Date }
                           into g
                           select new
                                      {
                                          g.Key.Date,
                                          IncidentsByHour = Enumerable.Range(0, 24).Select(h => g.Sum(x => x.IncidentsByHour[h])),
                                      }
    }
}

抛出异常:



我不确定如何解决此异常,因为它发生在 Raven 一侧。

按天分组的原因是我需要提取 365 天的统计数据,但仍然有一些按小时计算的基本信息。改为有两个索引会更好,一个按天,一个按小时(总共加载 365 + 24 条记录。我的理解是索引越大但越少越好)?

最佳答案

试试这个:

public class DailyStats : AbstractIndexCreationTask<Incident, DateStat>
{
  public DailyStats()
  {
    Map = docs =>
      from doc in docs
      select new
      {
        Date = doc.OccuredOn,
        IncidentsByHour = new Dictionary<int, int> { { doc.OccuredOn.Hour, 1 } }
      };

    Reduce = mapped =>
      from m in mapped
      group m by new { m.Date.Date }
      into g
      select new
      {
        Date = g.Key,
        IncidentsByHour = g.SelectMany(x => x.IncidentsByHour)
                           .GroupBy(x => x.Key)
                           .OrderBy(x => x.Key)
                           .ToDictionary(x => x.Key, x => x.Sum(y => y.Value))
      };
  }
}

这里唯一的区别是,在没有发生事故的几个小时内,您不会在字典中找到任何项目。

Raven 确实仍然存在某种错误。 map 应该可以这样写:
IncidentsByHour = Enumerable.Range(0, 24)
                      .ToDictionary(h => h, h => doc.OccuredOn.Hour == h ? 1 : 0)

但是由于某种奇怪的原因它失败了。我会将其报告为错误。

是的,与许多小索引相比,拥有更少的大索引通常更好。

关于mapreduce - 使用 RavenDB 索引按小时计数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19759687/

10-15 12:52