I was testing the usage of the 'and' operator and used the example mentioned in the documentation:
from every a1 = OrderStock1[action == "buy"] and
a2 = OrderStock2[action == "buy"] ->
b1 = StockExchangeStream[price > 70] ->
b2 = StockExchangeStream[price > 75]
select a1.action as action, b1.price as priceA, b2.price as priceB
insert into StockQuote partition by stockSymbol
I have noticed that if no event is sent to the OrderStock2 stream, a matching still happens.
The definition of 'and' in the documentation is : the occurrence of two events in any order. My understanding is that for a match to happen both OrderStock1 and OrderStock2 should receive events in any order followed by 2 events received in StockExchangeStream satisfying the price condition.
Any explanation of why a match happens even if no event is sent to the OrderStock2 stream??
Related
I am using SiddhiQL for complex event processing. My use case is to check whether two events of a particular type with certain filters occur within 15 mins.
Like for example -
If event1[filter 1] and event2[filter 2] within 15 mins
Insert into output stream
In my case any of the two events can occur first and i need to check whether after receiving the first event, do i receive the second event within 15 mins.
Is this possible in SiddhiQL?
EDIT #1 - I have defined my streams and events below (The below code does not work)
define stream RegulatorStream(deviceID long, roomNo int, tempSet double);
#sink(type = 'log', prefix = "LOGGER")
define stream outputStream (roomNo int,rooomNo int);
from e1 = RegulatorStream[roomNo==23] and e2 = RegulatorStream[e1.deviceID == deviceID AND roomNo ==24] within 5 minutes
select e2.roomNo,123 as rooomNo
insert into outputStream;
In above case, I need to alert when I receive events in my RegulatorStream having roomNo = 23 AND roomNo = 24 within 5 mins in any order with same deviceID.
How can this be achieved in SiddhiQL?
Yes this can achieved with Siddhi Patterns. Please refer the documentation on Siddhi Patterns in https://siddhi.io/en/v5.1/docs/query-guide/#pattern and examples in https://siddhi.io/en/v5.1/docs/examples/logical-pattern/.
You can use OR operation within the pattern to bypass the event occurrence order.
I am writing a pattern in Siddhi CEP like -
"from every e1=inputStream[(e1.name == 'A')]<2> -> e2=inputStream[(e2.name == 'B')<2:> within 10 seconds select 'rule1' as ruleId insert into outputStream"
The above query only executes once when I pass AABB into the stream, and then nothing happened after that. Even I pass AABB again.
When I write this -
"from every e1=inputStream[(e1.name == 'A')] -> e2=inputStream[(e2.name == 'B')<2:> within 10 seconds select 'ruel2' as ruleId insert into outputStream"
The above query works well for each ABB pattern.
Is there a way to achieve AAB and then pattern should start from next upcoming AAB when the window time expires.
group_events(G,Events) is true if Events is the list of events that
should be scheduled for the group G. My code is as follows:
studying(csen602, group2MET).
event_in_course(csen602, quiz1, quiz).
event_in_course(csen602, quiz2, quiz).
event_in_course(csen602, quiz3, quiz).
group_events(G,[Name|T]):-
studying(Course,G),
event_in_course(Course,Name,_),
\+member(Name,T),
group_events(G,T).
group_events(G,Events):-
member(Name,Events),
studying(Course,G),
event_in_course(Course,Name,Type).
what I get when using the query group_events(group2MET,E) is :
E = [quiz1|_G567]
E = [quiz2|_G502]
E = [quiz3|_G502]
E = [_G501, quiz1|_G505]
E = [_G501, quiz2|_G505]
E = [_G501, quiz3|_G505]
and so on...
I think the problem is with the member/2 predicate so any help how to solve this ?
I think you want
group_events(G,Events):-
setof(Event, Course^Desc^(
studying(Course,G),
event_in_course(Course,Event,Desc)
), Events).
The problem is that you're not 'starting' with an empty list, but with an uninstantiated list, to which you start adding events to be studied and which you are checking for membership.
But that list is still uninstantiated, so the tail of it, and any member you get from it, will be uninstantiated as well.
You want to find all events that need to be studied, so a good approach would be to first define a study_event(G, E) which defines an event E that needs to be studied for by a group G, and then use findall/3 to find all such events.
I keep trying to make complex correlations with Siddhi, on this occasion I have two input streams, web client consult and notices sent to clients visits, I want to generate an alert if the first stream for each client is repeated more than once as long as the second stream not It has occurred under two windows and depends of the status of this events.
define stream consults (idClient string,dniClient string,codProduct string,codSubProduct string,chanel string,time string )
define stream comercialActions(idClient string, idAccionComercial string,codProduct string,codSubProduct string,chanel string,time string,status string)
from consults[codProduct=='Fondos']#window.time(50 seconds) select idClient,codProduct, codSubProduct, chanel, time, count(idClient) as visitCount group by idClient insert into consultsAvg for current-events
from consultsAvg[visitCount==1] select idClient, '' as idAccionComercial,codProduct, codSubProduct ,chanel, time, 'temp' as status insert into comercialActions for all-events
from comercialActions[status=='temp' or status == 'Lanzada' ]#window.time(5 seconds) select idClient as idClient, codProduct, codSubProduct, chanel, status, count(idClient) as num_status group by idClient insert into acciones_generadas for all-events
from comercialActions[status=='temp' or status=='Aceptada' or status =='Rechazada'or status=='Caduca']#window.time(3 seconds) select idClient as idClient, codProduct, codSubProduct, chanel, status, count(idClient) as num_status group by idClient insert into acciones_realizadas for all-events
from consultsAvg[visitCount>=2]#window.time(50 seconds) as c join acciones_realizadas[num_status>=1]#window.time(5 seconds) as ag on c.idClient == ag.idClient and c.codProduct==ag.codProduct select c.idClient,c.codProduct,c.codSubProduct,c.chanel, c.time, count(c.idClient) as conteo insert into posible_ac for all-events
from posible_ac#window.time(5 seconds) as pac join acciones_generadas[num_status>=1]#window.time(1 seconds) as ar on pac.idClient == ar.idClient select pac.idClient,pac.codProduct,pac.codSubProduct,pac.chanel,pac.time,conteo, count(ar.idClient) as conteo2 insert into enviar_Ac
from enviar_Ac[conteo==1 and conteo2==1] select idClient, codProduct,codSubProduct, chanel, time insert into generar_accion_comercial
What I try to do is use intermediate streams to count the number of website hits when this is greater than or equal to 2 , I see if it has already made a commercial action for that customer through various joins...
I think I 've become very complicated and do not know if there would be a simpler solution ??? , considering it does not have the function Siddhi NOT Happened nor other join ( left join )
You can accomplish this with a pattern. In this case i assume that we have to wait for 1 minute for an event from the second stream and if there's none, and more than 1 event from the first, we are going to emit an output.
from consults#window.time(1 minute)
select idClient, count(idClient) as idCount, <select more attributes here>
insert into expiredConsultsStream for expired-events;
from expiredConsultsStream[idCount > 1]
select *
insert into filteredConsultsStream;
from firstEvent = consults ->
nonOccurringEvent = commercialActions[firstEvent.idClient == idClient]
or
triggerEvent = filteredConsultsStream[firstEvent.idClient == idClient]
select firstEvent.idClient as id, triggerEvent.idCount as idCount, nonOccurringEvent.idClient as nid
having( not (nid instanceof string))
insert into alertStream;
These are draft queries, so may require some modifications to get them working. The filteredConsultsStream contains consult events with more than 1 occurrence within the last minute.
In the last query we get the or of the conditions as:
nonOccurringEvent = commercialActions[firstEvent.idClient == idClient]
or
triggerEvent = filteredConsultsStream[firstEvent.idClient == idClient]
So the query will be triggered by one of those above occurrences. But, then we need to find whether the condition is triggered by commercialActions. For that we use the 'having' clause and check whether the id is null (id is null implies that the event is null, the non-occurrence). Finally we emit the output.
You can find a better description for a somewhat similar query here (that is new 4.0.0 version btw and there are small syntax changes)
Is there a better way to do this? Seems silly to have the same regex twice, but I want to indicate which phrase triggered the message content that was selected. Greenplum 4.2.2.4 (like PostgreSQL 8.2) on server.
SELECT
to_timestamp(extrainfo.startdate/1000)
,messages.timestamp
,users.username
,substring(messages.content from E'(?i)phrase number one|phrase\.two|another phrase|this list keeps going|lots\.of\*keyword phrases|more will be added in the future')
,messages.content
FROM users
LEFT JOIN messages ON messages.senderid = users.id
LEFT JOIN extrainfo ON extrainfo.username = users.username
WHERE extrainfo.type1 = 't'
AND messages.content ~* E'phrase number one|phrase\.two|another phrase|this list keeps going|lots\.of\*keyword phrases|more will be added in the future'
AND (extrainfo.type2 = 'f' OR extrainfo.type2 IS NULL)
Try using basic join:
SELECT
to_timestamp(extrainfo.startdate/1000)
,messages.timestamp
,users.username
,substring(messages.content from rgxp.rgxp )
,messages.content
FROM users
LEFT JOIN messages ON messages.senderid = users.id
join (
select E'(?i)phrase number one|phrase\.two|another phrase|this list keeps going|lots\.of\*keyword phrases|more will be added in the future'::text
as rgxp
) rgxp
on messages.content ~* rgxp.rgxp
LEFT JOIN extrainfo ON extrainfo.username = users.username
WHERE extrainfo.type1 = 't'
AND (extrainfo.type2 = 'f' OR extrainfo.type2 IS NULL)
This is a demo (for one table only): http://sqlfiddle.com/#!11/4a00d/2