perseo rules, how to get average of specific time window? - fiware

How can I use patterns in perseo rules with time windows? I have tried many different combinations, following the directions of EsperTech Tutorials, though, none of them was successful each time I post it to perseo. Any example for time window and how to get the average of any value (e.g. temperature) during that time will be highly appreciated. Trust me, before asking I have made a ton of efforts ;)
One working query for me is the following:
select *,\"temperature_range_XX-YY\" as ruleName, *, ev.temperature? as Temperature, ev.id? as Id, ev.datetime? as DateTime, ev.cid? as CID, current_timestamp as TS from pattern [every ev=iotEvent(cast(cast(temperature?,String),float)>XX or cast(cast(temperature?,String),float)<YY and type=\"sensors\")]
Of course, this query returns only any temperature outside XX and YY range. What I need is to get an alert if temperature is outside the range for specific time and what is the average of all values during that time.

To get an average you could use de avg() function within the select clause.
The following rule does work for me:
{
"name":"calculate_avg",
"text":"select *, avg(cast(cast(ev.NO2?,String),float)) as mediaNO2, ev.id? as id, \"calculate_avg\" as ruleName from pattern [every ev=iotEvent(type=\"AirQualityObserved\")].win:time(1 minute) group by ev.id?",
"action":{
"type":"update",
"parameters":{
"id":"${id}",
"type":"AirQualityAveraged",
"attributes": [
{
"name":"average",
"value":"${mediaNO2}"
}
]
}
}
}
I'd say your rule should be similar to:
"text":"select *,\"temperature_range_XX-YY\" as ruleName, *, avg(cast(cast(ev.temperature?, String), float)) as Temperature, ev.id? as Id, ev.datetime? as DateTime, ev.cid? as CID, current_timestamp as TS from pattern [every ev=iotEvent(cast(cast(temperature?,String),float)>XX or cast(cast(temperature?,String),float)<YY and type=\"sensors\")].win:time(1 minute)"

Related

Compare Calculated Fields to Current Date

Background:
We are trying to identify if notifications are due to go out against records that have configurable schedules. So, for instance, a record could have:
NotificationStep: 'week(s)'
NotificationCount: 3
StartDate: 2018-11-17
This would signal that 3 weeks after Nov 17 -- or the last time one of these notifications went out -- we need to send out a new notification.
In SQL this would involve comparing today to subquery (and possibly a union) utilizing the MAX() method.
Question:
Is there a good way to use today's date as the value by which you're comparing your calculated values against?
Something like:
myModel.find({
where:{
new Date(): {$gt: Notifications.max('date', {where: ... }
}
});
All you need is sequelize.where and sequelize.fn
Here you go :
myModel.find({
where:
sequelize.where(sequelize.fn('now') , {$gt: Notifications.max('date', {where: ... } )
});
Note : sequelize.fn('now') // <---- Give you current time from DB

couchbase N1ql query select with non-group by fields

I am new to couchbase and I have been going through couchbase documents and other online resources for a while but I could't get my query working. Below is the data structure and my query:
Table1:
{
"jobId" : "101",
"jobName" : "abcd",
"jobGroup" : "groupa",
"created" : " "2018-05-06T19:13:43.318Z",
"region" : "dev"
},
{
"jobId" : "102",
"jobName" : "abcd2",
"jobGroup" : "groupa",
"created" : " "2018-05-06T22:13:43.318Z",
"region" : "dev"
},
{
"jobId" : "103",
"jobName" : "abcd3",
"jobGroup" : "groupb",
"created" : " "2018-05-05T19:11:43.318Z",
"region" : "test"
}
I need to get the jobId which has the latest job information (max on created timestamp) for a given jobGroup and region (group by jobGroup and region).
My sql query doesn't help me using self-join on jobId.
Query:
/*
Idea is to pull out the job which was executed latest for all possible groups and region and print the details of that particular job
select * from (select max(DATE_FORMAT_STR(j.created,'1111-11-11T00:00:00+00:00')) as latest, j.jobGroup, j.region from table1 j
group by jobGroup, region) as viewtable
join table t
on keys meta(t).id
where viewtable.latest in t.created and t.jobGroup = viewtable.jobGroup and
viewtable.region = t.region
Error Result: No result displayed
Desired result :
{
"jobId" : "102",
"jobName":"abcd2",
"jobGroup":"groupa",
"latest" :"2018-05-06T22:13:43.318Z",
"region":"dev"
},
{
"jobId" : "103",
"jobName" : "abcd3",
"jobGroup" : "groupb",
"created" : " "2018-05-05T19:11:43.318Z",
"region" : "test"
}
If I understand your query correctly, this can be answered using 'group by' and no join. I tried entering your sample data and the following query gives the correct result:
select max([created,d])[1] max_for_group_region
from default d
group by jobGroup, region;
How does it work? It uses 'group by' to group documents by jobGroup and region, then creates a two-element array holding, for every document in the group:
the 'created' timestamp field
the document where the timestamp came from
It then applies the max function on the set of 2-element arrays. The max of a set of arrays looks for the maximum value in the first array position, and if there's a tie look at the second position, and so on. In this case we are getting the two-element array with the max timestamp.
Now we have an array [ timestamp, document ], so we apply [1] to extract just the document.
I'm seeing some inconsistencies and invalid JSON in your examples, so I'm going to do the best I can. First off, I'm using Couchbase Server 5.5 which provides the new ANSI JOIN syntax. There might be a way to do this in an earlier version of Couchbase Server.
Next, I created an index on the created field: CREATE INDEX ix_created ON bucketname(created).
Then, I use a subquery to get the latest date, aggregated by jobGroup and region. I then join the latest date from this query to the entire bucket and select the fields that (I think) you want in your desired result:
SELECT k.jobId, k.jobName, k.jobGroup, k.created AS latest, k.region
FROM (
SELECT j.jobGroup, j.region, MAX(j.created) as latestDate
FROM so j
GROUP BY j.jobGroup, j.region
) dt
LEFT JOIN so k ON k.created = dt.latestDate;
Problems with this approach:
If two documents have the exact same date, this isn't a reliable way to determine the latest. You can add a LIMIT 1 to the subquery, which would just pick one arbitrarily, or you could ORDER BY whatever your preference is.
Subquery performance: I don't know how large your data set is, but this could be pretty slow.
Requires Couchbase Server 5.5, which is currently in beta.
If you are using a different version of Couchbase Server, you may want to consider asking in the Couchbase N1QL Forums for a more expert answer.

N1QL query add hours and minutes

I want to add 5 hours and 30 minute in a time in N1QL. How can I do it ?
I have time like 2016-04-03T18:30:00.000Z I need to add 5:30.
You can use the DATE_ADD_STR(expression, n, part) Date Function. Your query would look similar to the following:
SELECT
DATE_ADD_STR(DATE_ADD_STR(old_time, 5, "hour"), 30, "minute") AS new_time, ...
FROM some_bucket
Documentation:
Performs date arithmetic. n and part are used to define an interval or
duration, which is then added (or subtracted) to the date string in a
supported format, returning the result. Parts:
"millennium"
"century"
"decade"
"year"
"quarter"
"month"
"week"
"day"
"hour"
"minute"
"second"
"millisecond"
Source: http://developer.couchbase.com/documentation/server/4.5/n1ql/n1ql-language-reference/datefun.html

How to write a view in couchbase for this sql statement

Let's say I have the following documents
Document 1
{
companyId: "1",
salesDate: "1425254400000" //this is UTC time as a long
}
Document 2
{
companyId: "1",
salesDate: "1425340800000" //this is UTC time as a long
}
Document 3
{
companyId: "2",
salesDate: "1425254400000" //this is UTC time as a long
}
I currently have my view set up as
function(doc, meta) { emit([doc.salesDate, doc.companyId], doc); }
Which is pulling back all 3 documents when using
?startkey=[1425254400000,"1"]&endkey=[1425340800000,"1"]
I'm not sure how to make it only pull back the sales for that date range by company id.
The sql version would be SELECT * FROM sales WHERE companyId = :companyId AND salesDate BETWEEN :rangeStart AND :rangeEnd
EDIT: I'm using the rest API.
When designing views for range queries with multiple query fields, the fixed query field(companyId) should be a prefix of the compound index and the range query field should be at the end. With the current view, Couchbase will emit every document where salesDate is within the range without considering companyId.
Reversing the order of keys will work:
function(doc, meta) {
emit([doc.companyId, doc.salesDate], doc);
}
Query:
?startkey=["1", 1425254400000]&endkey=["1", 1425340800000]
N.B. if salesDate is a string and not a numeric value, Couchbase will use lexicographic ordering to perform the range query.

Get count for each day in mongodb using aggregate or map reduce [duplicate]

This question already has answers here:
Count of records by Date MongoDB
(5 answers)
Closed 2 years ago.
How do i convert the below mysql query to mongodb query: SELECT count(*) as count , DATE_FORMAT( timestamp, '%d-%c-%Y' ) as day, timestamp as tm FROM visits WHERE 1 GROUP BY day ORDER BY tm. I want to use this on a nodejs so i am using native mongodb.
Get the number of pageviews for each day in mongodb where each pageview is stored along with the timestamp.
Your question lacks any effort on your part and we rarely just "give" people the answer like this, however, this one time:
NB: you cannot yet manipulate dates to cast them to different formats without some manual work yourself of picking the parts out and rejoining them. Because of this I have left out the date formatting you did and just used it as an object.
db.visits.aggregate([
{
$project: {
date: {day: {$dayOfMonth: '$timestamp'}, month: {$month: '$timestamp'}, year: {$year: '$timestamp'}},
//day: {concat: [date.day,date.mont,date.year]}
}
},
{$group: {_id: '$date', tm: '$timestamp', count: {$sum:1}}}
])
I found a working mongodb query using mapreduce which gives me the output time as unix time rather than the format I had mentioned in the question. But this was the query that was sorting the time properly. I had tried mongo group query but it did not sort according to time. The working mongo query is :
db.visits.mapReduce(
function(){
day = Date.UTC(this.timestamp.getFullYear(), this.timestamp.getMonth(), this.timestamp.getDate());
emit({day: day}, {count: 1});
},
function(key, values) {
var count = 0;
values.forEach(function(v) {
count += v['count'];
});
return {count: count};
},
{
out : {inline:1},
sort:{_id:1}
}
);