Negation for "every" statement? WSO2 CEP / Siddhi - wso2

Is there a simple way to negate the "every" statement? I am trying to implement a control tool that checks incoming purchase orders and requisitions. For each purchase order (PO) a requisition (REQ) has to be created before. The following code detects PO/REQ-pairs that match (positives) but I need all POs that do not have a corresponding REQ (negatives).
from every a1 = PO -> b1 = REQ[a1.ITEM_ID == b1.ITEM_ID and a1.QUANTITY == b1.QUANTITY and a1.CREATED_BY == b1.CREATED_BY] within 1 day select 'No REQ created before' as ALERT_MESSAGE insert into ALERT;

You can refer to sample on detecting non-occurrences with patterns.
However, since you want to check whether REQ event came before PO event you might need to use in-memory event tables to cater your requirement. Refer to the following sample on achieving the same using in-memory tables;
#Import('REQStream:1.0.0')
define stream REQ (ITEM_ID int, QUANTITY int, CREATED_BY string);
#Import('POStream:1.0.0')
define stream PO (ITEM_ID int, QUANTITY int, CREATED_BY string);
#Export('ALERTStream:1.0.0')
define stream ALERT (ITEM_ID int, ALERT string);
define table REQ_TABLE (ITEM_ID int, QUANTITY int, CREATED_BY string);
define trigger DAILY_TRIGGER at every 1 day;
from REQ
insert into REQ_TABLE;
-- check whether request exists before the purchase
from PO[not((REQ_TABLE.ITEM_ID == ITEM_ID and REQ_TABLE.QUANTITY == QUANTITY and REQ_TABLE.CREATED_BY == CREATED_BY) in REQ_TABLE)]
select ITEM_ID, 'No REQ created before' as ALERT
insert into ALERT;
-- purge reauests table daily
from DAILY_TRIGGER join REQ_TABLE
select REQ_TABLE.ITEM_ID, REQ_TABLE.QUANTITY, REQ_TABLE.CREATED_BY
insert into PURGE_STREAM;
-- if there's no matching purchase order came up for previous day
from PURGE_STREAM
select ITEM_ID, 'No purchase order came up for a day' as ALERT
insert into ALERT;
from PO
insert into DEL_STREAM;
from PURGE_STREAM
insert into DEL_STREAM;
-- delete corresponding request from table
from DEL_STREAM
delete REQ_TABLE
on REQ_TABLE.ITEM_ID == ITEM_ID and REQ_TABLE.QUANTITY == QUANTITY and REQ_TABLE.CREATED_BY == CREATED_BY;

Related

Netsuite suiteql how to get all available tables to query?

I am using Postman and Netsuite's SuiteQL to query some tables. I would like to write two queries. One is to return all items (fulfillment items) for a given sales order. Two is to return all sales orders that contain a given item. I am not sure what tables to use.
The sales order I can return from something like this.
"q": "SELECT * FROM transaction WHERE Type = 'SalesOrd' and id = '12345'"
The item I can get from this.
"q": "SELECT * FROM item WHERE id = 1122"
I can join transactions and transactionline for the sale order, but no items.
"q": "SELECT * from transactionline tl join transaction t on tl.transaction = t.id where t.id in ('12345')"
The best reference I have found is the Analytics Browser, https://system.netsuite.com/help/helpcenter/en_US/srbrowser/Browser2021_1/analytics/record/transaction.html, but it does not show relationships like an ERD diagram.
What tables do I need to join to say, given this item id 1122, return me all sales orders (transactions) that have this item?
You are looking for TransactionLine.item. That will allow you to query transaction lines whose item is whatever internal id you specify.
{
"q": "SELECT Transaction.ID FROM Transaction INNER JOIN TransactionLine ON TransactionLine.Transaction = Transaction.ID WHERE type = 'SalesOrd' AND TransactionLine.item = 1122"
}
If you are serious about getting all available tables to query take a look at the metadata catalog. It's not technically meant to be used for learning SuiteQL (supposed to make the normal API Calls easier to navigate), but I've found the catalog endpoints are the same as the SuiteQL tables for the most part.
https://{{YOUR_ACCOUNT_ID}}.suitetalk.api.netsuite.com/services/rest/record/v1/metadata-catalog/
Headers:
Accept application/schema+json
You can review all the available records, fields and joins in the Record Catalog page (Customization > Record Catalog).

How to search through rows and assign column value based on search in Postgres?

I'm creating an application similar to Twitter. In that I'm writing a query for the profile page. So when the user visits someone other users profile, he/she can view the tweets liked by that particular user. So for that my query is retrieving all such tweets liked by that user, along with total likes and comments on that tweet.
But an additional parameter I require is whether the current user has liked any of those tweets, and if yes, I want it to retrieve it as boolean True in my query so I can display it as liked in UI.
But I don't know how to achieve this part. Following is a sub-query from my main query
select l.tweet_id, count(*) as total_likes,
<insert here> as current_user_liked
from api_likes as l
INNER JOIN accounts_user ON l.liked_by_id = accounts_user.id
group by tweet_id
Is there an inbuilt function in postgres that can scan through the filtered rows and check whether current user id is present in liked_by_id. If so mark current_user_liked as True, else False.
You want to left outer join back into the api_likes table.
select l.tweet_id, count(*) as total_likes,
case
when lu.twee_id is null then false
else true
end as current_user_liked
from api_likes as l
INNER JOIN accounts_user ON l.liked_by_id = accounts_user.id
left join api_likes as lu on lu.tweet_id = l.tweet_id
and lu.liked_by_id = <current user id>
group by tweet_id
This will continue to bring in the rows you are seeing and will add a row for the lu alias on api_likes. If no such row exists matching the l.tweet_id and the current user's id, then the columns from the lu alias will be null.

How to perform getitem or query to retrieve last updated record in DynamoDB without using primary key

I've recently started learning DynamoDB and created a table 'Communication' with the following attributes (along with the DynamoDB type):
Primary Key Communication ID (randomly generated seq # or UUID): String
Sort Key User ID: String
Attributes/Columns:
Communication_Mode: String
Communication_Channel: String
Communication_Preference: String (possible values Y/N)
DateTime: Number
Use case: User can choose not to be communicated (Communication_Preference: N) and after a month user may opt for it (Communication_Preference: Y); meaning for the same User ID there can be more than 1 record as PartitionKey is randomly generated number
If I have to query above table and retrieve last inserted record for a specific userid do I need to create Global Secondary Index on DateTime.
Can someone correct me if my understanding is wrong or propose me the best option to meet above requirement. Thanks!

Kettle database lookup case insensitive

I've a table "City" with more than 100k records.
The field "name" contains strings like "Roma", "La Valletta".
I receive a file with the city name, all in upper case as in "ROMA".
I need to get the id of the record that contains "Roma" when I search for "ROMA".
In SQL, I must do something like:
select id from city where upper(name) = upper(%name%)
How can I do this in kettle?
Note: if the city is not found, I use an Insert/update field to create it, so I must avoid duplicates generated by case-sensitive names.
You can make use of the String Operations steps in Pentaho Kettle. Set the Lower/Upper option to Y
Pass the city (name) from the City table to the String operations steps which will do the Upper case of your data stream i.e. city name. Join/lookup with the received file and get the required id.
More on String Operations step in pentaho wiki.
You can use a 'Database join' step. Here you can write the sql:
select id from city where upper(name) = upper(?)
and specify the city field name from the text file as parameter. With 'Number of rows to return' and 'Outer join?' you can control the join behaviour.
This solution doesn't work well with a large number of rows, as it will execute one query per row. In those cases Rishu's solution is better.
This is how I did:
First "Modified JavaScript value" step for create a query:
var queryDest="select coalesce( (select id as idcity from city where upper(name) = upper('"+replace(mycity,"'","\'\'")+"') and upper(cap) = upper('"+mycap+"') ), 0) as idcitydest";
Then I use this string as a query in a Dynamic SQL row.
After that,
IF idcitydest == 0 then
insert new city;
else
use the found record
This system make a query for file's row but it use few memory cache

Query with Siddhi CEP using two times windows

I 'm trying to do a simple query but a two time windows ; the query would be something like trying to send a message to users who have visited a product of the web more than twice in the last four months, provided that you have already sent the last month advertising for this product.
define stream webvisit (idClient string, idProduct string, chanel string)
from webvisit select idCliente, idProducto, canal,sum(1) as visits group by idCliente insert into visits
from visits[idProduct=='Fondos' and visits > 2]#window.time(4) insert into alert
and will continue ?
You can do something like following:
define stream webvisit (idClient string, idProduct string, chanel string)
from visits[productId =='Fondos’]#window.time(4 days)
select idClient, idProduct, chanel, count(idClient) as visitCount
group by idClient
insert into visits;
from visits[visitCount > 2]
select *
insert into resultStream;
In the second query we get the visit counts for each client during last 4 days and in the last query we filter those results with count > 2.
EDIT:
Since you need to send a notification only if it's not been sent within the last day (assuming it's defined as: current time - 24 hours ), you can try following:
define stream webvisit (idClient string, idProduct string, chanel string);
from webvisit[idProduct == 'Fondos']#window.time(4 days)
select idClient, idProduct, chanel, count(idClient) as visitCount
group by idClient insert into visits for current-events;
from visits[visitCount > 2]#window.time(1 day)
select idClient, idProduct, chanel, count(idClient) as hitsForClientPerDay
insert into tempStream;
from tempStream[hitsForClientPerDay < 2]
select idClient, idProduct, chanel, 'your custom message here' as advertisement
insert into advertisementStream;
The second (1 day window) query keeps track of how many alerts ('hitsForClientPerDay') have been generated in the last 24 hours, the last query sends out the advertisement only if there hasn't been any during that period (note that hitsForClientPerDay will be 1 when the event comes since the current event is also considered for count(), so we check it as < 2 ).