0

I have a sequence of events which goes like this:

  1. Event A starts the sequence
  2. Multiple Events B happen
  3. Event C stops the sequence

I did that with a pattern [every A -> (B until C)], it seems to be correct (what do you think?). But I'm struggling to retrieve and aggregate infos from the B events that arose in the sequence. I'd like to simply have a count and maybe some avgs but nothing seems to work (example1 returns 1, example 2 returns 0 and example 3 return null, even if my B events are present).

insert into CreateMeasurement
select
    C.source            as source,
    "carDrivingAnalyse" as type,
    C.time              as time,
    {
        "example1", count(*),
        "example2", count(B),
        "example3", B.countOf()
    } as fragments

from pattern [
    every A = EventCreated(
        type = "Ignition",
        getString(A, "Ignition.status") = "ON")

    -> (
        B = EventCreated(
            type = "DrivingEvent",
            source = A.source,
            getString(B, "DrivingEvent.prop1") = getString(A, "Ignition.prop1"),
            getNumber(B, "DrivingEvent.prop2") = getNumber(A, "Ignition.prop2"))

        until C = EventCreated(
            type = "Ignition",
            getString(C, "Ignition.status") = "OFF",
            source = A.source,
            getString(C, "Ignition.prop1") = getString(A, "Ignition.prop1"),
            getNumber(C, "Ignition.prop2") = getNumber(A, "Ignition.prop2"))
    )
]
Gaetan L.
  • 649
  • 6
  • 20

2 Answers2

0

I would choose a different approach for this use case and use a context instead of a pattern:

create context EventContext
  context PartionBySource
    partition by event.source.value from EventCreated,
  context ContextBorders
    initiated by EventCreated(type="EventA") as startEvent 
    terminated by EventCreated(event.type="EventC");

It is already a more complex context because it uses two nested contexts. The is some basic coverage of contexts in the Cumulocity docs (http://cumulocity.com/guides/event-language/advanced/#contexts) but for this advanced usage I would recommend the more detailed esper documentation http://www.espertech.com/esper/release-5.3.0/esper-reference/html/context.html

In summary this context does this:

Based on the EventCreated stream it will first partition the events by their source device. It will create a new context partition every time there is an EventA (only if there is no context partition for this device at the moment). With an arrival of an EventC the context partition for this device will end.

Now you can make use of this context for example like this:

context EventContext
select
  count(*) as count,
  avg(getNumber(e, "speed")) as speed
from EventCreated e
where e.event.type = "EventB"
output last when terminated;

This statement uses the context. It will output the result at the moment the context partition ends (so when an EventC arrives). It will only output the last event (without the last keyword here it will output every event received while the partition was active). In this example it will output the number of events received during the existence of the context partition and the average value of the "speed" fragment in the EventB.

Note that it is not necessary to do any filtering by source here because the context already partitions the events on EventCreated by source.

TyrManuZ
  • 2,039
  • 1
  • 14
  • 23
  • Thanks for your answer, I'm reading the esper documentation and I'm trying to write the context but I'm already struggling to translate my pattern. See, I simplified my example by saying events B and C had to have the same source as A but in fact they have more properties to check (I edited my original post) and for now I'm not able to replicate the getString/getNumber functions in my context. – Gaetan L. Jun 16 '16 at 07:26
  • Also, what about conditional count? Something like "e.countOf(event -> getNumber(event, "c8y_HarshBehavior.speed") > 100)" except this doesn't work. – Gaetan L. Jun 16 '16 at 10:26
  • I would put the getNumber(event, "c8y_HarshBehavior.speed") > 100 to the where clause – TyrManuZ Jun 16 '16 at 11:19
  • I can't do that, I have a lot of things to count... Like I want the average speed but also the number of events where the speed was > 100, the number of times it was between 50 and 10, etc. – Gaetan L. Jun 16 '16 at 12:20
  • Just found some example in the esper solution patterns. You can use count like this `count(*, getNumber(event, "c8y_HarshBehavior.speed") > 100)`. Just tried it and it works. It only counts if the boolean expression is true. – TyrManuZ Jun 16 '16 at 12:34
  • How about "e.selectFrom(e -> .....).countOf()". You can always chain these. – user3613754 Jun 16 '16 at 12:49
  • That should be "e.where(e -> ... filter..).countOf()" – user3613754 Jun 16 '16 at 13:07
  • `count(*, event.speed >= 100.0)` did the trick thanks :) e.where did not return the expected result (it returned 0). – Gaetan L. Jun 16 '16 at 14:48
  • In the first approach with the pattern, "B" returns an array and "B.where(b -> ....).countOf()" filters and counts against that array. – goodie Jun 16 '16 at 21:28
0

I'm not an expert but "count()" never returns "null". Your observation is probably wrong in that respect. The "count()" is an aggregation function that counts the number of occurrences of whatever is in the from-clauses. For patterns it counts the number of pattern matches.

The "count(B)" counts the number of the (distinct) non-null values in the expression see doc. That also does not return "null".

The "example3" is what you want just make sure there are actually multiple B events arriving before C events according to your test data.

user3613754
  • 816
  • 1
  • 5
  • 5
  • My bad you're right, example 1 (count(*)) retrurns 1, logically, since the whole pattern matched once. Example 2 (count(B)) returns 0 and example 3 (B.countOf()) returns null, just as no events B were created. However it's not the case, there were events B. – Gaetan L. Jun 16 '16 at 06:49
  • Simplify the statement and post an example that uses the EPL tool here. The EPL tool link is http://esper-epl-tryout.appspot.com/epltryout/mainform.html – user3613754 Jun 16 '16 at 12:52