我正在使用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个记录。我的理解是更大但更少的索引是最好的)?
答案 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]"
}
});