I am trying to write an EPStatement that will match any event that does not have a specified field "similar" to another event in a sliding time window. For example only match events where "value" is at least distance 3 from any other event in the sliding window,
At t=t_0, E0={value=0} // Match
At t=t_1, E1={value=9} // Match
At t=t_2, E2={value=1} // Don't match since value is within 3 of E0.value
I am looking for a statement where I could use any expression that compares two values as the "similarity" metric. I looked at using patterns or match recognize but they don't seem to support this type of dynamic comparison to an unknown number of previous events.
select * from SomeEvent#keepall as e
having not window(*).anyOf(p => Math.abs(p.value - e.value) <= 3 and p.id != e.id)
The window(*) holds all events. The anyOf goes thru the window to find any that match. The p.id=e.id excludes the current event. field id being a unique id of the event that you may or may not have as an event property on the event.
Related
I have a quite simple problem to modelize and I don't have experience in Esper, so I may be headed the wrong way so I'd like some insight.
Here's the scenario: I have one stream of events "ParkingEvent", with two types of events "SpotTaken" and "SpotFree". So I have an Esper context both partitioned by id and bordered by a starting event of type "SpotTaken" and an end event of type "SpotFree". The idea is to monitor a parking spot with a sensor and then aggregate data to count the number of times the spot has been taken and also the time occupation.
That's it, no time window or whatsoever, so it seems quite simple but I struggle aggregating data. Here's the code I got so far:
create context ParkingSpotOccupation
context PartionBySource
partition by source from SmartParkingEvent,
context ContextBorders
initiated by SmartParkingEvent(
type = "SpotTaken") as startEvent
terminated by SmartParkingEvent(
type = "SpotFree") as endEvent;
#Name("measurement_occupation")
context ParkingSpotOccupation
insert into CreateMeasurement
select
e.source as source,
"ParkingSpotOccupation" as type,
{
"startDate", min(e.time),
"endDate", max(e.time),
"duration", dateDifferenceInSec(max(e.time), min(e.time))
} as fragments
from
SmartParkingEvent e
output
snapshot when terminated;
I got the same data for min and max so I'm guessing I'm doing somthing wrong.
When I'm using context.ContextBorders.startEvent.time and context.ContextBorders.endEvent.time instead of min and max, the measurement_occupation statement is not triggered.
Given that measurements have already been computed by the EPL that you provided, this counts the number of times the spot has been taken (and freed) and totals up the duration:
select source, count(*), sum(duration) from CreateMeasurement group by source
I have about 200,000 rows of 24 hour data as follows:
I can use the query to create a room node with time, roomtemp, and set temp as properties. Moreover, I can also, define the relationship of each room with its corresponding temperatures.
Now, I need to find:
all rows that show an update/increase/decrease from initial temperature till set temperature for all rooms. e.g. based on above data, I need:
Here I have discarded 5th row data as 16 was repetitive and showed no update(increase or decrease) in temp value. The temperature values continued till it reached set temperature '18'.
I can manually create the temperature states by giving its values one by one, but I am unsure how to MERGE the above requirement into the graph using Cypher.
Can I utilize any other programming language to obtain same results using Neo4j in conjunction?
Do I have to utilize in-graph time-tree for this scenario? Can I retrieve my results without creating a time tree?
Filter temparature by room and date (which can also be a date-node)
Sort by time
Collect into a list
Filter by differences in two subsequent temperatues
Turn list into rows
Here is a query that does this:
MATCH (r:Room)<-[:TEMP]-(t:Temparature)
WHERE t.time STARTS WITH "2016-01-01"
AND t.temp < room.temp ADN t.temp > {initial}
WITH t ORDER by t.time ASC
WITH collect(t) temps
WITH [idx in range(0,size(temps)-2) WHERE temps[idx].temp <> temps[idx+1].temp | temps[idx] ] as filtered
UNWIND filtered as t
RETURN t;
I am using esper and when I query my named window with timer:interval(10 sec) i get the same event duplicated after every 10 secs. I doesn't outputs other events present in the window.
here is the EPL
on pattern[every timer:interval(20 sec)] select DeviceIP, parent , child, Supress, Status from testZabbixProblem"
The engine outputs all rows in one call to the listener and delivering all rows at once as an array and not just one row.
I am trying to raise an event when the average value of a field is over a threshold for a minute. I have the object defined as:
class Heartbeat
{
public string Name;
public int Heartbeat;
}
My condition is defined as
select avg(Heartbeat) , Name
from Heartbeat.std:groupwin(Name).win:time(60 sec)
having avg(Heartbeat) > 100
However, the event never gets fired despite the fact that I fire a number of events with the Heartbeat value over 100. Any suggestions on what I have done wrong?
Thanks in advance
It confuses many people, but since time is the same for all groups you can simplify the query and remove the groupwin. The documentation note in this section explains why: http://esper.codehaus.org/esper-4.11.0/doc/reference/en-US/html_single/index.html#view-std-groupwin
The semantics with or without groupwin are the same.
I think you want group-by (and not groupwin) since group-by controls the aggregation level and groupwin controls the data window level.
New query:
select avg(Heartbeat) , Name from Heartbeat.win:time(60 sec) group by Name having avg(Heartbeat) > 100
I have implemented ESPER for my application need of CEP. While using EPL I encountered a specific scenario which is as follows:
I have combined two events with left outer join to make sure each event from first can trigger the statement and only those from second stream which contains specific property can come along. I have created a view to store unique data based on some fields. My EPLs are
#Name ('StmtCombinedEvent')
Insert into CombinedEvent
Select S as T1,
L as T2,
From pattern[every S= bussinessObject.Type1].std:unique(S.Id) as S
left outer join
bussinessObject.Type2.std:unique(name) as L
on S.name = L.name;
#Name ('StmtGroupingEvent')
Insert into Position
Select
G.T1 as T1
G.T2 as T2
From CombinedEvent.std:unique(T1.Id) as G;
I am using java.util.Map type for CombinedEvent dataType in configuration file
Now consider test scenario
Two events of type T1 having different Id but having same name has been entered into system
One event of type T2 is entered into system
Because of the view specification both event of type T1 resides into view and when event of type T2 enters into system, NewData parameter of type Event Bean contains both event of T1 (if I was using event listener in code), but as first EPL statement specifies it to insert into second statement it finds an error of mismatched type, as it was expecting event of type T2 for 'StmtGroupingEvent' but found Event Bean instead.
So I need to handle array type of data in EPL which would be cumbersome.
On the other hand if scenario is as follows:
Only one event of type T1 is entered into system.
One event of type T2 is entered into system.
This scenario doesn’t produce any error as Event Bean was successfully type casted to type T2.
So please suggest me any alternate way of doing this.
Thanks
What does "it finds an error of mismatched type" mean? If there was an exception logged please post it and post a small test class alongside to reproduce. Also make sure you are using the latest version of Esper, if there is a bug it has likely been fixed in a newer version.
Also, use "from bussinessObject.Type1.std:unique(S.Id)" instead of
pattern[every S= bussinessObject.Type1].std:unique(S.Id)", since the latter is a straight every it is the same.