Group/Apply

In den Beispielen in diesem Thema wird gezeigt, wie Ereignisse mittels der LINQ-Funktionalität "Gruppieren nach" in Ereignisgruppen partitioniert werden. Aggregationen und andere Vorgänge können in den Ereignisgruppen ausgeführt werden, sodass jede Gruppe getrennt berechnet wird. Der Satz von Vorgängen, der auf die einzelnen Gruppen angewendet wird, wird Anwendungsverzweigung genannt. Die Anwendungsverzweigung kann implizit innerhalb einer einzelnen Gruppe und Anwendungsanweisung bereitgestellt werden oder, wenn sie eine komplexere Unterabfrage enthält, als separate LINQ-Anweisung. Beachten Sie, dass Anwendungsverzweigungen innerhalb des Gruppen- und Anwendungskonstrukts geschlossen sind; beispielsweise ist es nicht möglich, den gruppierten Datenstrom mit einem Datenstrom zu verknüpfen, der nicht in der Gruppierung enthalten ist.

Beispiele

Im folgenden Beispiel werden Ereignisse nach der angegebenen modulo-Funktion gruppiert. Anschließend wird ein Momentaufnahmefenster auf jede Gruppe angewendet und der Durchschnitt über eine Nutzlastspalte für jede Gruppe getrennt berechnet. Die Anwendungsverzweigung besteht daher aus dem Fenster und der Aggregation.

// Assuming the following input event type for inputStream:
public class MyPayload 
{
    public int i; 
    public float j; 
}

var avgCount = from v in inputStream
               group v by v.i % 4 into eachGroup
               from window in eachGroup.SnapshotWindow(SnapshotWindowOutputPolicy.Clip)
               select new { avgNumber = window.Avg(e => e.j) };

Im vorherigen Beispiel wurde ein Datenstrom mit einem einzigen Nutzlastfeld erzeugt, der den Durchschnitt des Felds j in jedem Momentaufnahmefenster und pro Gruppe enthält.

Sie können auch eine Projektion des ursprünglichen Typs in einer GROUP BY-Klausel gruppieren, wie im folgenden Beispiel veranschaulicht.

var result = from e in source.AlterEventDuration(e => TimeSpan.FromMinutes(10))
                  group new { myVal = e.Value * 10 } by e.SourceId into g
                  from win in g.SnapshotWindow(SnapshotWindowOutputPolicy.Clip)
                  select new
                  {
                      avg = win.Avg(e => e.myVal)
                   };

In der Regel sollte der Gruppierungsschlüssel beibehalten werden, sodass das Aggregationsergebnis der jeweiligen Gruppe zugeordnet werden kann. Im nächsten Beispiel wird gezeigt, wie der Gruppierungsschlüssel abgerufen wird.

var avgCount = from v in inputStream
               group v by v.i % 4 into eachGroup
               from window in eachGroup.SnapshotWindow(SnapshotWindowOutputPolicy.Clip)
               select new { avgNumber = window.Avg(e => e.number), groupId = eachGroup.Key };

Es ist möglich, in mehreren Schlüsseln zu gruppieren, sodass jede eindeutige Schlüsselkombination im Eingabedatenstrom eine separate Gruppe ergibt. In diesem Fall müssen die Gruppierungsschlüssel in einer anonymen Typdefinition enthalten sein, sodass sie in der abschließenden Projektion explizit abgerufen werden können. Beachten Sie, dass auf alle Gruppierungsfelder verwiesen werden muss. Im folgenden Beispiel werden Ereignisse nach zwei Ereignisnutzlastfeldern gruppiert, und einer von ihnen wird ein neuer Schlüsselname zugewiesen.

// Assuming the following input event type for inputStream:
public class MyPayload 
{
    public int section; 
    public string category; 
    public float value; 
}

var avgCount = from v in inputStream
               group v by new { sec = v.section, v.category } into eachGroup
               from window in eachGroup.SnapshotWindow(SnapshotWindowOutputPolicy.Clip)
               select new { avgNumber = window.Avg(e => e.value), section = eachGroup.Key.sec, category = eachGroup.Key.category };

Die Anwendungsverzweigung kann komplexer sein und eine Folge von Operationen enthalten, wie im unten stehenden Beispiel veranschaulicht.

// Assuming the following input event type for inputStream:
public class MyPayload 
{
    public int section; 
    public string category; 
    public float value; 
}

var result = from s in source
                group s by s.section into sg
                from e in
                    (from e in sg
                    group e by e.category into cg
                    from win in cg.TumblingWindow(TimeSpan.FromMinutes(5), HoppingWindowOutputPolicy.ClipToWindowEnd)
                    select new { cat = cg.Key, top = win.Max(e => e.value) })
                select new { sec = sg.Key, e.cat, e.top };

Im folgenden Beispiel wird ein Datenstrom von Energiemessgeräte-Ablesungen angenommen, der die Daten mehrerer Messgeräte umfasst. Im Beispiel wird jede Ablesung mit einer Anmerkung zum Durchschnitt für die letzten 10 Minuten des entsprechenden Messgeräts versehen. Die Abfrage gruppiert die eingehenden Daten zunächst nach der Messgeräte-ID. In jeder dieser Gruppen wird der Durchschnitt für 10 Minuten berechnet und mit den ursprünglichen Messgeräteereignissen verknüpft.

// Assuming the following input event type for sensorStream:
public class MeterReading
{
    public string meterId; 
    public float usage; 
}

var resultB = from s in sensorStream
              group s by s.meterId into g
              from e in
                  (from left in g
                  from right in
                      (from win in g
                          .AlterEventDuration(e => TimeSpan.FromMinutes(10))
                          .SnapshotWindow(SnapshotWindowOutputPolicy.Clip)
                      select new { avg = win.Avg(e => e.usage) })
                  select new { right.avg, left.usage })
              select new { slidingAvg = e.avg, e.usage, g.Key };

Wie oben erwähnt, kann die Funktion zum Darstellen der Anwendungsverzweigung keine anderen eingehenden Datenströme (mit Ausnahme von applyIn) integrieren.

Siehe auch

Konzepte

StreamInsight-Serverkonzepte

Verwenden von Ereignisfenstern

Momentaufnahmefenster