numberDisplay - filter by max key - dc.js

I have a dc.js dashboard that has historical Headcount, Sickness etc information that is grouped by Month / Period. The users of the Dashboards want to see the most recent Month's data in number displays across the top (e.g Headcount, Sickness rate etc).
My data:
var data= [
{ "Month": "01/02/2014","Period": 201402,"Heads": 15123,"SchedHours":146000,"Sickness": 0,},
{ "Month": "01/03/2014","Period": 201403,"Heads": 15100,"SchedHours": 146000,"Sickness": 0,},
{ "Month": "01/04/2014","Period": 201404,"Heads": 14900,"SchedHours": 146000,"Sickness": 0,},
{ "Month": "01/05/2014","Period": 201405,"Heads": 14800,"SchedHours": 146000,"Sickness": 0,},
{ "Month": "01/06/2014","Period": 201406,"Heads": 14750,"SchedHours": 146000,"Sickness": 0,},
{ "Month": "01/07/2014","Period": 201407,"Heads": 14720,"SchedHours": 146000,"Sickness": 0,},
{ "Month": "01/08/2014","Period": 201408,"Heads": 14000,"SchedHours": 146000,"Sickness": 0,},
{ "Month": "01/09/2014","Period": 201409,"Heads": 13750,"SchedHours": 146000,"Sickness": 0,},
{ "Month": "01/10/2014","Period": 201410,"Heads": 13500,"SchedHours": 146000,"Sickness": 0,},
{ "Month": "01/11/2014","Period": 201411,"Heads": 13200,"SchedHours": 146000,"Sickness": 0,},
....]
I can work out how to do this by default when the dashboard first loads using a variable:
maxPeriod = dimPeriod.top(1)[0].Period;
But I'm struggling to work out how to update the variable above to update the numberDisplay to always filter it to show the Heads by the max Period or Month.
I'm currently showing the latest number of "Heads" using a function Gordon kindly provided in another question:
function choose_bin(group, key) {
return {
value: function() {
return group.all().filter(kv => kv.key === key)[0].value;
}
}
}
My group is then:
var latestMonth = choose_bin(groupHeads3, maxPeriod);
and the numberDisplay:
numberChart
.group(latestMonth)
.valueAccessor(x => (x))
.formatNumber(d3.format(".0f"));
I have a basic jsfiddle that shows the problem (as soon as a filter is applied, the value is 0): https://jsfiddle.net/kevinelphick/mzpoe555/2/
What I'm aiming to do, is for the Heads value to update based on the highest period that's filtered in the line chart. I'm also looking to include the month prior to the highest period value, and provide a comparison of the two to show a trend.
Thank you in advance.

You're just not calculating quite enough stuff at runtime. You need to calculate maxPeriod and everything subsequent to that every time the group is queried. You'll probably want to do something like this (which works if you drop it into your JSFiddle:
var latestMonth = {
all: function() {
maxPeriod = dimPeriod.top(1)[0].Period;
return [choose_bin(groupHeads3, maxPeriod).value()]
}
}

Related

What is the correct format for `child-resource-references` responses?

TS-0004 Table 7.5.2-2 states that the R/6 (retrieve child-resource-references) call (?fu=1&rcn=6) should return an m2m:resourceRefList. Is this correct? At least two open-source implementations i have seen return m2m:URIList for this query.
Is there anywhere listed examples that show a more complete list of responses for combinations of query parameters?
You are right. fu=1 (discovery request) and rcn=6 should return a m2m:resourceRefList. Such as:
{
"m2m:ch": [
{
"nm": "aResource",
"typ": 99,
"val": "cse-in/aResource"
},
{
"nm": "anotherResource",
"typ": 99,
"val": "cse-in/anotherResource"
}
]
}
There are a couple of examples in the developer guides: https://www.onem2m.org/developer-guides

Microsoft Teams: get timezone of user?

I'm developing a bot for MS Teams and I'm looking to know the timezone of a user, to deliver messages at an appropriate time (e.g. not in the middle of the night).
I didn't found something appropriate in the bot framework REST API. Although messages we receive include a 'clientInfo.country' property, which is a start, but definitely not enough to time messages as we would like.
On every message to a user, there is an entities[] collection, one of which is details of the user's locale. For example (copied/pasted from here):
"entities": [
{
"locale": "en-US",
"country": "US",
"platform": "Windows",
"timezone": "America/Los_Angeles",
"type": "clientInfo"
}
],
And the answer is: there’s a localTimestamp property that can be used to get the time offset, which is good enough for what I need.
From #Savageman 's answer
And the answer is: there’s a localTimestamp property that can be used to get the time offset, which is good enough for what I need.
We can solve the issue "NOT Receive the timezone" by mapping the utcOffset of localTimestamp and country in entities to timezone.
I wrote a javascript code to get timezone such as "Asia/shanghai" by using the "localTimestamp": "2019-08-06T18:23:44.259+08:00" and "country": "CN" from Session in Teams message.
More details in my github readme.md.
let moment = require("moment-timezone");
let ct = require("countries-and-timezones");
let partOfSampleSession = {
"message": {
"entities": [
{
"country": "CN",
"locale": "zh-CN",
"platform": "Web",
"type": "clientInfo"
}
],
"localTimestamp": "2019-08-06T18:23:44.259+08:00"
}
}
function getTimezoneFromSession(session) {
// Get the name of country, such as "CN", "JP", "US"
let country = session.message.entities[0].country;
// Get the localTimestamp from message in session, such as "2019-08-06T18:23:44.259+08:00"
let localTimestamp = session.message.localTimestamp;
// Caculate the utfOffset of "localTimestamp", such as "480" by "2019-08-06T18:23:44.259+08:00"
let utcOffsetOfLocalTime = moment().utcOffset(localTimestamp).utcOffset();
// Mapping country to an object array which contains utcOffsets and it's corresponding timezones
// One element from mxTimezones is {"utcOffset": "480", "name": "Asia/Shanghai"}
let mxTimezones = ct.getTimezonesForCountry(country);
// get the same timezone as localtime utcOffset from timezones in a country
let timezone = "";
mxTimezones.forEach(mxTimezone => {
if (mxTimezone.utcOffset == utcOffsetOfLocalTime) {
timezone = mxTimezone.name;
}
});
return timezone;
}
let timezone = getTimezoneFromSession(partOfSampleSession);
// timezone = "Asia/Shanghai"
console.log(timezone);
// example of ct.getTimezonesForCountry("US")
// mxTimezones = [
// {
// "name": "America/New_York",
// "utcOffset": "-300",
// },
// {
// "name": "America/Los_Angeles",
// "utcOffset": "-480",
// }
// ...
// 27 elements
// ...
// ]

How to get all maxes from couchbase using map/reduce?

I've got a lot of records like:
{
"id": "1000",
"lastSeen": "2018-02-26T18:49:21.863Z"
}
{
"id": "1000",
"lastSeen": "2017-02-26T18:49:21.863Z"
}
{
"id": "2000",
"lastSeen": "2018-02-26T18:49:21.863Z"
}
{
"id": "2000",
"lastSeen": "2017-02-26T18:49:21.863Z"
}
I'd like to get the most recent records for all ids. So in this case the output would be the following(most recent record for ids 1000 and 2000):
{
"id": "1000",
"lastSeen": "2018-02-26T18:49:21.863Z"
}
{
"id": "2000",
"lastSeen": "2018-02-26T18:49:21.863Z"
}
With N1QL, this would be
SELECT id, MAX(lastSeen) FROM mybucket GROUP BY id
How would I do this using a couchbase view and map/reduce?
Thanks!
I am far from a regular user of map/reduce, and there may be more efficient JavaScript, but try this:
Map
function (doc, meta) {
emit(doc.id, doc.lastSeen);
}
Reduce
function reduce(key, values, rereduce) {
var max = values.sort().reverse()[0];
return max;
}
Filter: ?limit=6&stale=false&connection_timeout=60000&inclusive_end=true&skip=0&full_set=true&group_level=1
The idea is to sort all the values being emitted (lastSeen). Since they are ISO 8601 and can be lexigraphically sorted, sort() works just fine. You want the latest, so that's what the reverse() is for (otherwise you'd get the oldest).
The filter has a group_level of 1, so it will group by the doc.id field.
You can query by descending and reduce to first one on list as below:
Map:
function (doc, meta) {
emit(doc.id, doc.lastSeen);
}
Reduce:
function reduce(key, values, rereduce) {
return values[0];
}
Filter:
?inclusive_end=true&skip=0&full_set=&group_level=1&descending=true
This will eliminate the overhead of sorting the grouped values inside reduce function.

RethinkDB query with group by date

I have the following documents stored:
{
"date": 1437429603126,
"id": "7c578fe6-5eeb-466c-a79a-628784fd0d16",
"quote": {
"c": "+2.45",
"c_fix": "2.45",
"ccol": "chg",
"cp": "1.89",
"cp_fix": "1.89",
"div": "0.52",
"e": "NASDAQ",
"ec": "+0.58",
"ec_fix": "0.58",
"eccol": "chg",
"ecp": "0.44",
"ecp_fix": "0.44",
"el": "132.65",
"el_cur": "132.65",
"el_fix": "132.65",
"elt": "Jul 20, 5:59PM EDT",
"id": "22144",
"l": "132.07",
"l_cur": "132.07",
"l_fix": "132.07",
"lt": "Jul 20, 4:09PM EDT",
"lt_dts": "2015-07-20T16:09:40Z",
"ltt": "4:09PM EDT",
"pcls_fix": "129.62",
"s": "2",
"t": "AAPL",
"yld": "1.57"
}
}
And looking to run a query that selects fields quote.t, quote.l, quote.c, quote.cp where t is AAPL order by date. The piece that is missing is grouping by multiple documents in the same day. The logic I need is take the oldest document where quote.t = AAPL. So basically there should only be a single document returned each day, and that document should have the greatest date.
Here is what I have so far, missing the grouping of multiple documents in a single day though.
r.db('macd').table('daily_closes').filter({
'quote': {
't': 'AAPL'
}
}).orderBy('date').pluck('date', {
'quote': [
't',
'l',
'c',
'cp'
]
})
Also, I have secondary indexes, how can I use those in the query?
You need to group by date, but you store day as epoch time. So you need a way to turn it into day and group. We can then group by that value, and sort the reduction array in desc order, then get the first element of that array with nth.
r.table('daily_closes').filter({
'quote': {
't': 'AAPL'
}
}).orderBy('date')
.pluck('date', {
'quote': [
't',
'l',
'c',
'cp'
]
}).group(r.epochTime(r.row('date').div(1000)).date()).orderBy(r.desc('date')).nth(0)
You may got something like this:
{
"group": Mon Jul 20 2015 00:00:00 GMT+00:00 ,
"reduction": {
"_date": Mon Jul 20 2015 00:00:00 GMT+00:00 ,
"date": 1437429603126 ,
"quote": {
"c": "+2.45" ,
"cp": "1.89" ,
"l": "132.07" ,
"t": "AAPL"
}
}
}
So let's reduce noise, we will ungroup it. Basically without ungroup, you are operating on sub stream of each group, when you ungroup, they become a single document. We also only care about data inside reduction, because that contains a single, first document. Here is the final query:
r.table('daily_closes').filter({
'quote': {
't': 'AAPL'
}
}).orderBy('date')
.pluck('date', {
'quote': [
't',
'l',
'c',
'cp'
]
})
.group(r.epochTime(r.row('date').div(1000)).date()).orderBy(r.desc('date')).nth(0)
.ungroup()
.getField('reduction')
Now, let's use index.
First, filter is slow, and limit to 100k document, order without index is slow. Let's switch to getAll with an index. But we cannot order with an index follow by a getAll. So we will use this trick:
Create an index for both value and using between:
r.table('daily_closes').indexCreate('quote_date', [r.row('quote')('t'),r.row('date')])
Now, we use between:
r.table('daily_closes')
.between(['AAPL', r.minval], ['AAPL', r.maxval],{index: 'quote_date'})
.pluck('date', {
'quote': [
't',
'l',
'c',
'cp'
]
})
.group(r.epochTime(r.row('date').div(1000)).date())
.orderBy(r.desc('date')).nth(0)
.ungroup()
.getField('reduction')
I hope this helps.

How does changes() work in rethinkdb?

Example from the home page of rethinkdb.com doesn't work as expected.
r.db("test").tableCreate("game");
r.db("test").table("game").indexCreate("score");
r.db("test").table("game").insert({name: "brandon", score: 60});
r.db("test").table("game").insert({name: "leon", score: 80});
r.db("test").table("game").insert({name: "connor", score: 100});
r.db("test").table("game").orderBy({index: "score"}).limit(3).changes()
Output:
{ "new_val": { "id": "c727b9eb-5aaa-46f9-bc09-a6c879cfbfa0" , "name":
"brandon" , "score": 60 } } { "new_val": { "id":
"b59d4314-b78c-48c9-8780-0f9d3a6b6887" , "name": "leon" , "score": 80
} } { "new_val": { "id": "519343b1-cd98-4969-8f07-7bff5d981c81" ,
"name": "connor" , "score": 100 } }
r.db("test").table("game").insert({name: "mike", score: 70});
Nothing changes but must be changed due to ordering by score.
r.db("test").table("game").get("519343b1-cd98-4969-8f07-7bff5d981c81").update({score: 50}) // {name: "connor"}
Still nothing..
So why ordered list is not updates as it should be?
This is a bug in the data explorer, unfortunately. It was fixed in https://github.com/rethinkdb/rethinkdb/issues/4852 and the fix will be pushed out as a point release soon. Until it's released I'd recommend using one of the drivers to test these queries instead.
This appears to be a failure of the Web interface. Running these commands from a client driver (I tried it with the JavaScript driver on 2.1.3 and 2.1.4) shows the changes as expected, it's just that the Data Explorer does not update correctly. If you swap tabs to Table View and back you can see that the cursor has received the changes at the bottom.

Resources