我有这样的文件:
order : 1
event : { timestamp: 1/1/2012, employeeName: "mick" },
event : { timestamp: 1/1/2012, employeeName: "mick" },
event : { timestamp: 1/2/2012, employeeName: "rick" },
event : { timestamp: 1/3/2012, employeeName: "mick" }
order : 2
event : { timestamp: 1/2/2012, employeeName: "mick" },
event : { timestamp: 1/2/2012, employeeName: "rick" }
我想运行map-reduce查询,以返回按日期分组的结果列表,其中包含每个订单的员工事件计数。
在这种情况下,Mick在单个订单上的1/1上有2个事件。所有其他日子,员工在11月2日和3日的每个订单上都有一次活动。所以我需要一个MAP功能,结果如下:
{ orderId: 1, date: 1/1/2012, employee: "mick", orderEventsCount: 2 },
{ orderId: 1, date: 1/2/2012, employee: "rick", orderEventsCount: 1 },
{ orderId: 2, date: 1/2/2012, employee: "mick", orderEventsCount: 1 },
{ orderId: 2, date: 1/2/2012, employee: "rick", orderEventsCount: 1 },
{ orderId: 1, date: 1/3/2012, employee: "mick", orderEventsCount: 1 }
然后我需要一个REDUCE函数来获取这些结果并仅按日期分组,并在一个订单上返回每天有多个事件的员工的计数:
{ date: 1/1/2012, multipleEventsPerOrdercount: 1 },
{ date: 1/2/2012, multipleEventsPerOrdercount: 0 },
{ date: 1/3/2012, multipleEventsPerOrdercount: 0 }
由于Mick是唯一一个在单个订单上的单个日期有多个事件的员工,因此结果只返回一个员工在一个日期的订单上有多个事件的计数。
在.NET中使用LINQ编写此map-reduce Raven查询的最佳方法是什么?
由于
答案 0 :(得分:1)
假设您的课程如下:
public class Order
{
public string Id { get; set; }
public List<Event> Events { get; set; }
}
public class Event
{
public DateTime Timestamp { get; set; }
public string EmployeeName { get; set; }
}
然后您要求的索引将如下所示:
public class Orders_EventCountsByDate :
AbstractIndexCreationTask<Order, Orders_EventCountsByDate.Result>
{
public class Result
{
public DateTime Date { get; set; }
public double Count { get; set; }
}
public Orders_EventCountsByDate()
{
Map = orders => from order in orders
from evt in order.Events
let subtotal = order.Events.Count(x => x.EmployeeName == evt.EmployeeName && x.Timestamp == evt.Timestamp)
select new
{
evt.Timestamp.Date,
Count = subtotal > 1 ? (1.0 / subtotal) : 0
};
Reduce = results => from result in results
group result by result.Date
into g
select new
{
Date = g.Key,
Count = g.Sum(x => x.Count)
};
}
}
你会像这样使用它:
var counts = session.Query<Orders_EventCountsByDate.Result,
Orders_EventCountsByDate>();
这里的诀窍在于您在地图中确定您希望每个事件对计数的贡献程度。如果只有一个事件,则您贡献零。当有多个事件时,每个事件只占总数的一小部分。这些分数后来在减少中总结,使您回到接近整数。双浮点数学可以让你回到整数,但你仍然可能想要在客户端代码中舍入到最接近的整数,只是为了安全。
这也假设所有事件都在同一时区,您不关心夏令时更改,或者时间是UTC。如果两者都没有,那么你应该使用DateTimeOffset,在决定每个员工的一天概念时,你还需要考虑更多。