【原创】StreamInsight查询系列(十四)——查询模式之相异计数
上篇文章介绍了查询模式中基本模式部分,这篇博文将介绍相异计数,即在事件流中找出互不相同的事件并进行计数。
测试数据准备
为了方便测试查询,我们首先准备一个静态的测试数据源:
var dataWithDups = new [] { new { EventType = 'A', OrderNumber = 101, Action = 'S', Price = 8.65, Shares = 2000 }, new { EventType = 'A', OrderNumber = 102, Action = 'S', Price = 8.60, Shares = 500 }, new { EventType = 'A', OrderNumber = 103, Action = 'B', Price = 8.40, Shares = 1200 }, new { EventType = 'A', OrderNumber = 104, Action = 'B', Price = 8.50, Shares = 1000 }, new { EventType = 'A', OrderNumber = 105, Action = 'S', Price = 8.70, Shares = 500 }, new { EventType = 'A', OrderNumber = 105, Action = 'S', Price = 8.70, Shares = 500 }, // 重复事件 new { EventType = 'A', OrderNumber = 104, Action = 'B', Price = 8.50, Shares = 1000 }, // 重复事件 };
接下去将dataWithDups转变为点类型复杂事件流:
var dupStream = dataWithDups.ToPointStream(Application, t => PointEvent.CreateInsert(DateTime.UtcNow.AddTicks(t.OrderNumber), t), AdvanceTimeSettings.StrictlyIncreasingStartTime);
互异计数
问题1:怎样过滤掉重复事件?
更明确的步骤是:
- 查看10分钟内的数据(找出给定时间周期内的重复事件);
- 按照所有的字段进行分组
- 传统的LINQ(或SQL语句)定义“唯一性”是指记录中所有的字段都相同;
- StreamInsight中可以指定一部分字段来指定“唯一性”(例如不考虑时间戳);
- 从每个分组中取出1个事件
下面按照上述步骤编写查询实现:
第1步&第2步:将事件持续事件延长5分钟并按照所有字段进行分组。分组的结果是相同的事件会被放在同一个组中。
var distinctGroups = from e in dupStream.AlterEventDuration( e => TimeSpan.FromMinutes(10)) group e by new { e.EventType, e.OrderNumber, e.Action, e.Price, e.Shares};
第3步:从每个分组中取出相同事件中的1个到结果事件流中。
var noDuplicates = distinctGroups.ApplyWithUnion(apply => (from win in apply.SnapshotWindow(SnapshotWindowOutputPolicy.Clip) from t in win orderby t.EventType select t).Take(1), e => new { EventType = e.Payload.EventType, OrderNumber = e.Payload.OrderNumber, Action = e.Payload.Action, Price = e.Payload.Price, Shares = e.Payload.Shares });
最后移除掉重复项的结果如下:
问题2:怎样统计互异事件的总数?
与问题1类似,我们需要将相同的事件划分到同样的组中,然后从中取其一,最后进行聚合操作,即统计总数。
第1步,按照所有字段分组并统计同一分组内事件总数:
var distinctQuery = from e in dupStream group e by new { e.EventType, e.OrderNumber, e.Action, e.Price, e.Shares } into dGroups from win in dGroups.TumblingWindow(TimeSpan.FromMinutes(10), HoppingWindowOutputPolicy.ClipToWindowEnd) select new { // 事件数量(多少重复事件) EventCount = win.Count() };
第2步:统计分组数:
var query2 = from win in distinctQuery .SnapshotWindow(SnapshotWindowOutputPolicy.Clip) select new { DistinctCount = win.Count() };
在LINQPad中输出结果如下:
下一篇将介绍StreamInsight查询模式中的窗口比率部分。