【原创】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:怎样过滤掉重复事件?

更明确的步骤是:

  1. 查看10分钟内的数据(找出给定时间周期内的重复事件);
  2. 按照所有的字段进行分组
    1. 传统的LINQ(或SQL语句)定义“唯一性”是指记录中所有的字段都相同;
    2. StreamInsight中可以指定一部分字段来指定“唯一性”(例如不考虑时间戳);
  3. 从每个分组中取出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查询模式中的窗口比率部分。

posted @ 2011-09-05 09:46  StreamInsight  阅读(1083)  评论(0编辑  收藏  举报