(The aggregation of the HIGValue is last entry per day per user, averaged over the month, but with a custom rounding function)
XXX, YYY, ZZZ are other object types in the db that need kpi aggregations, but these are simple counts per month.
namespace xxx.Indexes
{
public class KPIIndex : AbstractMultiMapIndexCreationTask<KPIIndex.Result>
{
public class Result
{
public string UserId { get; set; }
public int xxxCount { get; set; }
public int yyyCount { get; set; }
public int zzzCount { get; set; }
public int HigValue { get; set; }
public int HigCounter { get; set; }
public int Month { get; set; }
public int Year { get; set; }
public int YearMonth { get; set; }
}
public override string IndexName
{
get
{
return "HRProcessKPI";
}
}
public KPIIndex()
{
//add maps for xxx, yyy and zzz with the appropraite count of 1 for each instance
AddMap<XXX>(items => from xxx in items
select
new Result
{
UserId = xxx.SubjectUser.UserId,
xxxCount = 1,
yyyCount = 0,
zzzCount = 0,
HigValue = -10,
HigCounter = 0,
Month = xxx.EventDate.Month,
Year = xxx.EventDate.Year,
YearMonth = (xxx.EventDate.Year * 100) + xxx.EventDate.Month
});
AddMap<YYY>(items => from yyy in items
select
new Result
{
UserId = yyy.SubjectUser.UserId,
xxxCount = 0,
yyyCount = 1,
zzzCount = 0,
HigValue = -10,
HigCounter = 0,
Month = yyy.EventDate.Month,
Year = yyy.EventDate.Year,
YearMonth = (yyy.EventDate.Year * 100) + yyy.EventDate.Month
});
AddMap<ZZZ>(items => from zzz in items
select
new Result
{
UserId = zzz.Subject.UserId,
xxxCount = 0,
yyyCount = 0,
zzzCount = 1,
HigValue = -10,
HigCounter = 0,
Month = zzz.StartOfProcess.Month,
Year = zzz.StartOfProcess.Year
,
YearMonth = (zzz.StartOfProcess.Year * 100) + zzz.StartOfProcess.Month
});
AddMap<HIGEntry>(items =>
from hig in items
group hig by new {hig.Subject.UserId, hig.CaptureDate.Date} into g
let MaxDayDatePerUser = g.Max(h => h.CaptureDate)
from dayhig in g
where dayhig.CaptureDate == MaxDayDatePerUser
select new Result
{
UserId = dayhig.Subject.UserId,
xxxCount = 0,
yyyCount = 0,
zzzCount = 0,
HigValue = dayhig.Value,
HigCounter = 1,
Month = dayhig.CaptureDate.Month,
Year = dayhig.CaptureDate.Year,
YearMonth = (dayhig.CaptureDate.Year * 100) + dayhig.CaptureDate.Month
}
);
//the reduce function groups by the month, userid and year and then sums each count
Reduce = results => from result in results
group result by new { result.Month, result.UserId, result.Year } into g
select new Result
{
UserId = g.Key.UserId,
xxxCount = g.Sum(x => x.xxxCount),
yyyCount = g.Sum(x => x.yyyCount),
zzzCount = g.Sum(x => x.zzzCount),
HigValue =
new Func<double, int>(unrounded => (((int) Math.Floor(Math.Abs(unrounded))) +
((Math.Abs(unrounded)%1) >= 0.25 ? 1 : 0)) * ((unrounded < 0) ? -1 : 1)
).Invoke(
(double)g.Aggregate(0, (a, b) => b.HigValue > -10 ? a + b.HigValue : a) / (double)g.Sum(h => h.HigCounter)
),
HigCounter = g.Sum(h => h.HigCounter),
Month = g.Key.Month,
Year = g.Key.Year,
YearMonth = (g.Key.Year * 100) + g.Key.Month
};
}
}
}