Agrupar y aplicar

En los ejemplos de este tema se muestra cómo dividir los eventos por grupos de eventos mediante la funcionalidad "agrupar por" de LINQ. Las agregaciones y otras operaciones se pueden realizar en los grupos de eventos, para que cada grupo se calcule por separada. El conjunto de operaciones aplicado a cada grupo se denomina rama de aplicación. La rama de aplicación se puede proporcionar implícitamente dentro de una única instrucción de agrupación y aplicación o, si contiene una subconsulta más compleja, como una instrucción LINQ independiente. Observe que las ramas de aplicación están cerradas dentro de la construcción de agrupar y aplicar; por ejemplo, no es posible combinar el flujo agrupado con un flujo externo a la agrupación.

Ejemplos

En el siguiente ejemplo los eventos se agrupan por la función modulo especificada. A continuación, se aplica una ventana de instantánea a cada de grupo y se calcula el promedio por una columna de carga en cada grupo por separado. Así, la rama de aplicación está compuesta por la ventana y la agregación.

// 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) };

El ejemplo anterior generó un flujo con un único campo de carga, que contiene el promedio del campo j dentro de cada ventana de instantánea y por grupo.

También puede agrupar una proyección del tipo original en una cláusula "group by", tal como se muestra en el siguiente ejemplo.

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)
                   };

Normalmente, la clave de agrupación se debe retener para que el resultado de la agregación se pueda asociar al grupo respectivo. En el ejemplo siguiente se muestra cómo recuperar la clave de agrupación.

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 };

Se puede agrupar por varias claves, de forma que cada combinación de claves única de la secuencia de entrada genere un grupo independiente. En este caso, las claves de agrupación deben estar en una definición de tipo anónima para que se puedan recuperar explícitamente en la última proyección. Tenga en cuenta que se debe hacer referencia a todos los campos de agrupación. En el siguiente ejemplo los eventos se agrupan por dos campos de carga del evento y se asigna un nuevo nombre de clave a uno de ellos.

// 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 };

La rama de aplicación puede ser más compleja y contener una serie de operaciones, tal como se muestra en el ejemplo siguiente.

// 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 };

En el siguiente ejemplo, se supone un flujo de lecturas de medidor de energía, que contiene los datos de varios medidores. El ejemplo anota cada lectura con la media de los últimos 10 minutos para el mismo medidor. La consulta primero agrupa los datos entrantes por identificador de medidor. En cada grupo de este tipo, se calcula la media del periodo de 10 minutos y se combina con los eventos de medidor originales.

// 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 };

Tal como se ha mencionado anteriormente, la función que representa la rama de aplicación no puede integrar otros flujos de entrada excepto applyIn.

Vea también

Conceptos

Conceptos de servidor de StreamInsight

Utilizar ventanas de eventos

Ventanas de instantánea