Compartilhar via


Junções

Os exemplos deste tópico mostram como correlacionar valores de fluxos diferentes usando uma operação de junção. Uma operação de junção compara cada evento de um fluxo de entrada com cada evento de um ou mais fluxos de entrada do tipo CepStream. Se os intervalos de tempo válidos se sobrepuserem e a condição de junção for mantida, a operação gerará um evento de saída.

Como normalmente acontece em LINQ, a condição de junção pode ser especificada como um predicado de junção por igualdade entre dois fluxos de entrada através da cláusula on … equals ou de uma cláusula where que pode fazer referência a dois ou mais fluxos de entrada. O predicado de junção por igualdade pode comparar campos únicos, como where x.a equals y.a ou chaves compostas; por exemplo, where {x.a, x.b} equals {y.a, y.b} ou where x equals y.

Exemplos

Junção interna

Uma operação de junção interna retorna todos os eventos de um ou mais fluxos de entrada quando o predicado de junção entre eles é avaliado como true. Um predicado de junção é uma expressão que compara os campos de carga dos dois fluxos de eventos que estão sendo unidos. Uma junção interna elimina todos os eventos que não têm um evento correspondente no outro fluxo de eventos especificado.

Junção de igualdade

O exemplo a seguir compara eventos do fluxo stream1 com eventos do fluxo stream2. Os eventos do fluxo que atendem aos critérios de igualdade definidos na cláusula on (além da sobreposição nos intervalos de tempo dos dois eventos) são unidos e geram um novo evento que contém os campos de carga i e j do evento e1 e o campo j do evento e2.

// Assuming the following input event type for both stream1 and stream2.
public class MyPayload
{
    public int i;
    public float j;
}

var equiJoin = from e1 in stream1
               join e2 in stream2
               on e1.i equals e2.i
               select new { e1.i, e1.j, e2.j };

O predicado de igualdade permite a comparação de tipos primitivos e compostos. Por exemplo, é possível unir on {e1i, e1j} equals {e2i, e2j}.

Junção cruzada

Uma operação de junção cruzada (produto Cartesiano) retorna um fluxo de eventos que é a combinação de cada evento do primeiro fluxo com cada evento do segundo fluxo, na duração da sobreposição dos intervalos do evento de cada fluxo. Uma expressão de filtro pode ser usada na cláusula where para limitar os eventos de cada fluxo de entrada. É importante observar que, para dois fluxos de entrada, uma junção cruzada com uma cláusula where que verifica a igualdade é equivalente a uma junção por igualdade com a cláusula on … equals correspondente. Para predicados de desigualdade ou mais de dois fluxos de entrada, uma junção cruzada precisará ser usada.

No exemplo a seguir, os eventos em stream1 com um valor no campo de carga i superior a 3 são unidos a eventos de stream2 com um valor no campo de carga j inferior a 10.

var crossJoin = from e1 in stream1
                from e2 in stream2
                where e1.i > 3 && e2.j < 10
                select new { e1.i, e2.j };

Left Anti-Semi-Join

A left anti-semi-join só gerará um resultado de junção para cada evento no lado esquerdo se o resultado da junção comum for vazio, para cada momento determinado. Essa operação é útil para detectar intervalos com eventos zero.

var leftAntiSemiJoin = from left in stream1 
                       where (from right in stream2 
                              where left.v == right.v
                              select right).IsEmpty()
                       select left;

A ilustração a seguir mostra o resultado de junção anterior com dois fluxos de entrada de exemplo, supondo que a condição de junção é avaliada como true. O resultado de junção comum intermediário também é exibido.

Exemplo de anti semi join com dois fluxos

Unindo vários fluxos

Você pode unir vários fluxos em uma única consulta, conforme mostrado no exemplo a seguir.

var slopetest = from f in fastSignal
                          from s in slowSignal
                          from r in refSignal
                          select new { alarm = f.avg / s.avg < r.Threshold };