Jointures

Les exemples de cette rubrique montrent comment mettre en corrélation les valeurs de différents flux à l'aide d'une opération de jointure. Une opération de jointure compare chaque événement d'un flux d'entrée avec chaque événement d'un ou de plusieurs autres flux d'entrée de type CepStream. Si leurs intervalles de temps valides se chevauchent et que la condition de jointure se maintient, l'opération produit un événement de sortie.

Comme d'habitude avec LINQ, la condition de jointure peut être spécifiée en tant que prédicat d'équi-jointure entre deux flux d'entrée en utilisant la clause on … equals ou where qui peut désigner au moins deux flux d'entrée. Le prédicat d'équi-jointure peut comparer des champs uniques, tels que where x.a equals y.a, ou des clés composites, telles que where {x.a, x.b} equals {y.a, y.b} ou where x equals y.

Exemples

Jointure interne

Une opération de jointure interne renvoie tous les événements d'au moins deux flux d'entrée lorsque le prédicat de jointure entre eux prend la valeur True. Un prédicat de jointure est une expression qui compare les champs de charge utile des flux d'événements joints. Une jointure interne élimine tous les événements pour lesquels il n'existe pas d'événement correspondant dans les autres flux d'événements spécifiés.

Équi-jointure

Dans l'exemple suivant, les événements du flux stream1 sont comparés aux événements du flux stream2. Les événements du flux qui répondent aux critères d'égalité définis dans la clause on (et dont les intervalles de temps se chevauchent) sont joints et sortent dans un nouvel événement contenant les champs de charge utile i et j de l'événement e1 et le champ j de l'événement 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 };

Le prédicat d'égalité permet de comparer les types primitifs et les types composés. Par exemple, il est possible de joindre on {e1i, e1j} equals {e2i, e2j}.

Jointure croisée

Une opération de jointure croisée (produit cartésien) renvoie un flux d'événements qui associe chaque événement du premier flux à chaque événement du second flux, pendant la durée de chevauchement des intervalles de l'événement de chaque flux. Une expression de filtre peut être utilisée dans la clause where pour limiter les événements de chaque flux d'entrée. Il est important de noter que pour deux flux d'entrée, une jointure croisée avec une clause where qui recherche l'égalité est équivalente à une équi-jointure avec la clause on … equals correspondante. Pour les prédicats d'inégalité ou plusieurs flux d'entrée, une jointure croisée doit être utilisée.

Dans l'exemple suivant, les événements de stream1 dont la valeur du champ de charge utile i est supérieure à 3 sont joints aux événements de stream2 dont la valeur du champ de charge utile j est inférieure à 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

L'opérateur Left Anti Semi Join produit un résultat de jointure pour chaque événement du côté gauche uniquement si le résultat de la jointure ordinaire est vide, pour tout point précis dans le temps. Cette opération est utile pour détecter des écarts avec zéro événement.

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

L'illustration suivante montre le résultat de la jointure ci-dessus entre deux flux d'entrée fournis comme exemple, en supposant que la condition de jointure retourne True. Le résultat de la jointure ordinaire intermédiaire est également affiché.

Exemple d'anti-semi-jointure avec deux flux

Jointure de plusieurs flux

Vous pouvez joindre plusieurs flux dans une seule requête, comme le montre l'exemple suivant.

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