使用RavenDB索引按小时计数

时间:2013-11-03 23:51:50

标签: mapreduce ravendb

我正在使用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])),
                                      }
    }
}

抛出异常:

  

第201行,第22位:错误CS1502 - “System.Linq.Enumerable.ToDictionary(System.Collections.Generic.IEnumerable,System.Func,System.Collections.Generic.IEqualityComparer)”的最佳重载方法匹配无效的参数   第201行,第72位:错误CS1503 - 参数2:无法从'System.Func'转换为'System.Func'   第201行,第106位:错误CS1503 - 参数3:无法从'System.Func'转换为'System.Collections.Generic.IEqualityComparer'   第274行,第22位:错误CS1928 - 'System.Collections.Generic.IEnumerable'不包含'Select'的定义和最佳扩展方法重载'System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable, System.Func)'有一些无效的参数   第274行,第54位:错误CS1503 - 参数2:无法从'System.Func'转换为'System.Func'

我不知道如何解决这个异常,因为它发生在Raven方面。

白天分组的原因是我需要提取365天的统计数据,但仍然需要一小时的基本信息。相反,有两个索引,一天一个,一个一个小时(总共加载了365 + 24个记录。我的理解是更大但更少的索引是最好的)?

2 个答案:

答案 0 :(得分:2)

试试这个:

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确实存在某种错误。地图能够用以下方式编写:

IncidentsByHour = Enumerable.Range(0, 24)
                      .ToDictionary(h => h, h => doc.OccuredOn.Hour == h ? 1 : 0)

但由于一些奇怪的原因它失败了。我会报告这是一个错误。

是的,通常比较多的小索引更少的索引更好。

答案 1 :(得分:1)

根据您希望结果显示的内容,您可以尝试分面搜索。 http://ravendb.net/docs/2.5/client-api/faceted-search

显然,只有你已经深入到你感兴趣的那一天,这才有用。我也会编写代码来生成范围,但它看起来像下面这样:

var myCoolStuff = session.Query<Incident, SomeIndex>().Where().ToFacet(
new List<Facet>
          {
              new Facet
                  {
                      Name = "OccuredOn"
                      Mode = FacetMode.Ranges,
                      Ranges =
                          {
                              "[2013-01-01T00:00 TO 2013-01-01T01:00]",
                              "[2013-01-01T01:00 TO 2013-01-01T02:00]",
                              "[2013-01-01T02:00 TO 2013-01-01T03:00]",
                              "[2013-01-01T03:00 TO 2013-01-01T04:00]",
                              "[2013-01-01T04:00 TO 2013-01-01T05:00]",
                              "[2013-01-01T05:00 TO 2013-01-01T06:00]",
                              "[2013-01-01T06:00 TO 2013-01-01T07:00]",
                              "[2013-01-01T07:00 TO 2013-01-01T08:00]",
                              "[2013-01-01T08:00 TO 2013-01-01T09:00]",
                              "[2013-01-01T09:00 TO 2013-01-01T10:00]",
                              "[2013-01-01T10:00 TO 2013-01-01T11:00]",
                              "[2013-01-01T11:00 TO 2013-01-01T12:00]",
                              "[2013-01-01T12:00 TO 2013-01-01T13:00]",
                              "[2013-01-01T13:00 TO 2013-01-01T14:00]",
                              "[2013-01-01T14:00 TO 2013-01-01T15:00]",
                              "[2013-01-01T15:00 TO 2013-01-01T16:00]",
                              "[2013-01-01T16:00 TO 2013-01-01T17:00]",
                              "[2013-01-01T17:00 TO 2013-01-01T18:00]",
                              "[2013-01-01T18:00 TO 2013-01-01T19:00]",
                              "[2013-01-01T19:00 TO 2013-01-01T20:00]",
                              "[2013-01-01T20:00 TO 2013-01-01T21:00]",
                              "[2013-01-01T21:00 TO 2013-01-01T22:00]",
                              "[2013-01-01T22:00 TO 2013-01-01T23:00]",
                              "[2013-01-01T23:00 TO 2013-01-02T00:00]"
                          }                      
});