siddhi icon indicating copy to clipboard operation
siddhi copied to clipboard

Support more than one logical operator for pattern

Open mohanvive opened this issue 5 years ago • 5 comments

Description: There are multiple requests from community users on $subject in https://github.com/siddhi-io/siddhi/issues/1611 , https://github.com/siddhi-io/siddhi/issues/1610 and https://github.com/siddhi-io/siddhi/issues/1461. We need to revisit the pattern implementation/design of Siddhi to achieve this.

mohanvive avatar Jan 09 '20 06:01 mohanvive

@mohanvive @suhothayan Is there any sort of a timeline for this? If you think I can help with something, just let me know.

salvalcantara avatar Jan 15 '20 20:01 salvalcantara

In #1461 and #1610, some workarounds were given for rewriting queries involving multiple unordered events (in the meantime support for them is added)...but after checking with the simple pattern A and B and C the workaround seems not to be working:

define stream A (value int);
define stream B (value int);
define stream C (value int);

@sink(type='log')
define stream output(msg string);

from A and B select "A and B" as msg insert into o1;
from o1 and C select "A and B and C" as msg insert into output;

I have verified that the above app is not detecting all the possible (ordered) patterns for A, B, and C. For example, the output is not emitting any event for the following inputs:

c1 b1 a1
a1 c1 b1
b1 a1 c1

which looks like a bug to me (on the Siddhi Editor at least, the output triggers only after a1 b1 c1). Could you confirm whether there is a bug here @mohanvive ?

salvalcantara avatar Feb 10 '20 13:02 salvalcantara

@mohanvive There are basically two workarounds that have worked for me so far:

  1. Generating all the permutation patterns as discussed in #1610 (and along the lines of the match_recognize permute operator, see this):
from A -> B -> C select "A and B and C" as msg insert into output;
from A -> C -> B select "A and B and C" as msg insert into output;
from B -> A -> C select "A and B and C" as msg insert into output;
from B -> C -> A select "A and B and C" as msg insert into output;
from C -> A -> B select "A and B and C" as msg insert into output;
from C -> B -> A select "A and B and C" as msg insert into output;
  1. Using an in-memory table:
define table tableABC(id string);

-- Update state
from A select "A" as id update or insert into tableABC on tableABC.id == id;
from B select "B" as id update or insert into tableABC on tableABC.id == id;
from C select "C" as id update or insert into tableABC on tableABC.id == id;

-- Check conditions on arrival of events
from A[("A" == tableABC.id in tableABC) and ("B" == tableABC.id in tableABC) and ("C" == tableABC.id in tableABC)] select "A and B and C" as msg insert into output;
from B[("A" == tableABC.id in tableABC) and ("B" == tableABC.id in tableABC) and ("C" == tableABC.id in tableABC)] select "A and B and C" as msg insert into output;
from C[("A" == tableABC.id in tableABC) and ("B" == tableABC.id in tableABC) and ("C" == tableABC.id in tableABC)] select "A and B and C" as msg insert into output;

Overall I think option 2 is preferable, since it scales linearly with the number of conditions, whereas option1 requires n! pattern queries in the general case (6 for the case at hand, n=3).

I don't know how the support for multiple logical operator patterns is planned to be implemented, but maybe this table approach can provide some guidelines.

salvalcantara avatar Feb 10 '20 16:02 salvalcantara

We can use patterns to achieve this A and B and C within 15 mins

define stream RegulatorStream(roomNo int, deviceId long) define stream tempStream (value int); define stream tempStream1 (value int);

@sink(type='log') define stream output(msg string);

from RegulatorStream[roomNo == 24] select 0 as value insert into tempStream;

from RegulatorStream[roomNo == 25] select 1 as value insert into tempStream;

from RegulatorStream[roomNo == 26] select 1 as value insert into tempStream1;

from every e1 = tempStream -> e2 = tempStream[(e1.value == 0 and e2.value == 1) or (e1.value == 1 and e2.value == 0) ] within 15 mins select 0 as value insert into tempStream1;

from every e1 = tempStream1-> e2 = tempStream1[(e1.value == 0 and e2.value == 1) or (e1.value == 1 and e2.value == 0) ] within 15 mins select "alert" as msg insert into outputStream;

akhi19 avatar Feb 16 '20 06:02 akhi19

@suhothayan What is the current state? Could you please share your thoughts on how to deal with this issue?

salvalcantara avatar Mar 10 '20 12:03 salvalcantara