Apama 10.15.0 | Developing Apama Applications | Developing Apama Applications in EPL | Defining Queries | Finding and acting on event patterns | Defining event patterns | Query followed-by operator
 
Query followed-by operator
You can specify the -> (followed-by) operator in the find statement. The -> operator matches events that come after each other. The event on the left of the operator always arrives in the correlator before the event on the right. In other words, the -> operator is always between two distinct events. For example, A as a1 -> A as a2 requires the arrival of two instances of an A event for the query to find a match. Also, any where clauses in the find statement must evaluate to true for an event pattern to match. Finally, the match set always includes the latest event.
Thus, the rules for when there is a match for an event pattern that specifies one or more followed-by operators are as follows. All of these requirements must be met for there to be a match.
*There are events in the partition that match the subpatterns on both sides of the followed-by operator(s).
*There is a match for the subpattern on the left of a followed-by operator before there is a match for the subpattern on the right of a followed-by operator. One event cannot match more than one subpattern in an event pattern.
*If a subpattern contains a where clause then the where clause must evaluate to true for the subpattern to match.
*The match set contains the latest event.
*If there is more than one candidate event set for the match set then it is the most recent candidate event set that is the match set. See Event matching policy.
The following sections provide examples that illustrate these rules.
Two coassignments
Consider the following code in which the Withdrawal event contains only one field of interest, which is the country. Assume that the query partitions arriving Withdrawal events into windows according to the account number field.
find Withdrawal as w1 -> Withdrawal as w2
where w1.country = "UK" and w2.country = "Narnia" {
// Recent card fraud in Narnia against UK customers
send SuspiciousWithdrawal(w2) to "Suspicious";
}
To make it easier to understand the behavior of the -> operator in more populated windows, the following example events omit the account number field but include a unique identifier field. Suppose the window for this query contains the following events, in arrival order top to bottom:
Withdrawal("Belgium", 1)
Withdrawal("UK", 2)
Although there is a Withdrawal event followed by another Withdrawal event, the where clause does not evaluate to true so there is no match. Now suppose the window contains these events:
Withdrawal("UK", 3)
Withdrawal("Narnia", 4)
Now the query finds a match. There is a Withdrawal event followed by another Withdrawal event, and the where clause evaluates to true. Withdrawal("UK, 3") is coassigned to w1 and Withdrawal("Narnia", 4) is coassigned to w2. The query executes the statements in its find block, which in this example is to send the event that triggered the match.
In this example, the Withdrawal events in the match set arrived consecutively. However, this is not a requirement. Consider a window that contains the following events:
Withdrawal("UK", 5)
Withdrawal("Belgium", 6)
Withdrawal("Belgium", 7)
Withdrawal("Narnia", 8)
When Withdrawal("Narnia", 8) is added to its window, the query finds a match because the Withdrawal("UK", 5) event is followed by the Withdrawal("Narnia", 8) event and the where clause evaluates to true for those two events. The effective behavior is that all combinations of events in the window are inspected to find a combination that matches. The Withdrawal("UK, 5") event is coassigned to w1 and Withdrawal("Narnia, 8") is coassigned to w2. The query executes the statements in its find block.
A match must include the event that arrived most recently in the window (the latest event). This ensures that a query does not detect more than one match for the same combination of events. In the previous example, the query found a match when the Withdrawal("Narnia", 8) event arrived.
Imagine that another Withdrawal event arrives and the window now contains the following events:
Withdrawal("UK", 5)
Withdrawal("Belgium", 6)
Withdrawal("Belgium", 7)
Withdrawal("Narnia", 8)
Withdrawal("Belgium", 9)
While the window still contains the Withdrawal("UK", 5) event followed by the Withdrawal("Narnia", 8) event, the arrival of the Withdrawal("Belgium", 9) event does not trigger a new match because it is not part of that combination. However, suppose the Withdrawal("Narnia", 10) event arrives. The window now contains the following events:
Withdrawal("UK", 5)
Withdrawal("Belgium", 6)
Withdrawal("Belgium", 7)
Withdrawal("Narnia", 8)
Withdrawal("Belgium", 9)
Withdrawal("Narnia", 10)
Now the query finds a new match. The Withdrawal("UK", 5) event is followed by the just arrived Withdrawal("Narnia", 10) event and the where clause evaluates to true for these two events. This match set contains Withdrawal("UK", 5) and Withdrawal("Narnia", 10). While this match set contains the same Withdrawal("UK", 5) event that was in the previous match set, it is a new match set because it contains the event that arrived most recently, which is the Withrawal("Narnia", 10) event.
Suppose that the Withdrawal("Narnia", 14) event has just arrived in the following window:
Withdrawal("Belgium", 11)
Withdrawal("UK", 12)
Withdrawal("UK", 13)
Withdrawal("Narnia", 14)
In this situation, there is a match set that contains the two most recently arrived events, that is, Withdrawal("UK", 13) and Withdrawal("Narnia", 14). The Withdrawal("UK", 12) event is not part of the match set because it is not the most recently arrived Withdrawal event whose country field is "UK".
Three coassignments
The code example below shows three coassignments in the find statement. This query partitions the arriving events into windows according to their Automated Transaction Machine identifier numbers (atmId).
query RepeatedMaxWithdrawals {
inputs {
Withdrawal() key atmId within 4 minutes;
}
find Withdrawal as w1 -> Withdrawal as w2 -> Withdrawal as w3
where w1.amount = 500 and w2.amount = 500 and w3.amount = 500 {
log "Suspicious withdrawal: " + w3.toString() at INFO;
}
}
Each window contains the Withdrawal events that occurred in the last four minutes at a particular ATM. For simplicity, the following examples show only the amount and transactionId event fields. Suppose the following events are in the window and that they arrived in order from top to bottom:
Withdrawal(500, 101) w1
Withdrawal(500, 102) w2
Withdrawal(500, 103) w3
After the third event arrives, the event pattern is matched, the where clause evaluates to true, and the events are coassigned to w1, w2, and w3 as shown above.
Another event arrives in the window:
Withdrawal(500, 101)
Withdrawal(500, 102) w1
Withdrawal(500, 103) w2
Withdrawal(500, 104) w3
When the fourth event arrives there is a new match and the events are coassigned as shown above. The Withdrawal(500, 101) event is not part of the new match set. A match set always includes the most recent events that satisfy the event pattern and that allow the where clause to evaluate to true.
Another event arrives and the window now contains these events:
Withdrawal(500, 101)
Withdrawal(500, 102)
Withdrawal(500, 103)
Withdrawal(500, 104)
Withdrawal(100, 105)
The latest event, Withdrawal(100, 105), does not have 500 in its amount field. Consequently, its arrival in the window does not trigger a new match because a match set must always include the latest event. While the window still contains three events that satisfy the event pattern, the actions in the find block are not executed as a result of the arrival of Withdrawal(100, 105) because it did not trigger a new match.
Another event arrives and the window now contains these events:
Withdrawal(500, 101)
Withdrawal(500, 102)
Withdrawal(500, 103) w1
Withdrawal(500, 104) w2
Withdrawal(100, 105)
Withdrawal(500, 106) w3
With the arrival of the Withdrawal(500, 106) event, there is a new match and the events are coassigned as shown above. The coassigned events are the three most recently arrived events that satisfy the event pattern. It does not matter that Withdrawal(100, 105) arrived after some events that are in the match set. That event does not satisfy the event pattern and so it is not included in the match set.
Finally, suppose all of the following events have arrived in the window within the specified four minutes:
Withdrawal(500, 101)
Withdrawal(500, 102)
Withdrawal(500, 103)
Withdrawal(500, 104)
Withdrawal(100, 105)
Withdrawal(500, 106) w1
Withdrawal(500, 107) w2
Withdrawal(100, 108)
Withdrawal(100, 109)
Withdrawal(500, 110) w3
As you can see, the latest event causes a new match. This match set does not include the two events that arrived just before the latest event. Those two events do not satisfy the event pattern.