Join

Negli esempi di questo argomento viene illustrato come correlare valori di flussi diversi tramite un'operazione di join. Quest'ultima consente di confrontare ogni evento di un flusso di input con ogni evento di uno o più flussi di input di tipo CepStream. Se gli intervalli di tempo validi si sovrappongono e la condizione di join è valida, l'operazione consente di generare un evento di output.

Come si verifica abitualmente in LINQ, la condizione di join può essere specificata come un predicato di equijoin tra due flussi di input utilizzando la clausola on … equals o una clausola where che può far riferimento a due o più flussi di input. Il predicato di equijoin può consentire di confrontare singoli campi, come where x.a equals y.a o chiavi composte, ad esempio where {x.a, x.b} equals {y.a, y.b} o where x equals y.

Esempi

Inner join

Un'operazione di inner join consente di restituire tutti gli eventi da due o più flussi di input quando tramite il predicato di join tra di essi viene restituito true. Un predicato di join è un'espressione che consente di confrontare i campi payload dei flussi di eventi per cui è in corso la creazione di un join. Un inner join consente di eliminare tutti gli eventi per i quali non vi è un evento corrispondente negli altri flussi di eventi specificati.

Equijoin

Nell'esempio seguente gli eventi nel flusso stream1 vengono confrontati con gli eventi nel flusso stream2. Per gli eventi del flusso che soddisfano i criteri di uguaglianza definiti nella clausola on (oltre alla sovrapposizione negli intervalli di tempo dei due eventi) viene creato un join e tali eventi vengono restituiti in un nuovo evento contenente i campi payload i e j dell'evento e1 e il campo j dell'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 };

Il predicato di uguaglianza consente il confronto sia di tipi primitivi sia di tipi composti. Ad esempio, è possibile creare un join di on {e1i, e1j} equals {e2i, e2j}.

Cross Join

Un'operazione di cross join (prodotto cartesiano) consente di restituire un flusso di eventi che rappresenta la combinazione di ogni evento del primo flusso con ogni evento del secondo flusso, per la durata della sovrapposizione degli intervalli dell'evento di ogni flusso. È possibile utilizzare un'espressione di filtro nella clausola where per limitare gli eventi di ogni flusso di input. È importante notare che per due flussi di input, un cross join con una clausola where che consente di verificare l'uguaglianza è equivalente a un equijoin con la clausola on … equals corrispondente. Per i predicati non di uguaglianza o per più di due flussi di input, è necessario utilizzare un cross join.

Nell'esempio seguente per gli eventi di stream1 con un valore nel campo payload i maggiore di 3 viene creato un join con gli eventi di stream2 con un valore nel campo payload j minore di 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

Il left anti semi join produce un risultato di join per ogni evento sul lato sinistro solo se il risultato del join comune è vuoto, per ogni punto nel tempo. Questa operazione è utile per rilevare gap con zero eventi.

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

Nella figura seguente è illustrato il risultato del join precedente con due flussi di input di esempio, presupponendo che la condizione di join restituisca true. Viene illustrato anche il risultato del join comune intermedio.

Esempio di Anti Semi Join con due flussi

Creazione di join di più flussi

È possibile creare un join di più flussi in un'unica query, come mostrato nell'esempio seguente.

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