node_redis get zrange withscores - node.js

Does anybody know how can I get members with scores by node redis?
I tried something like this:
client.ZRANGE(key, 0, -1, withscores, function(err, replies) {
});
Thanks.

This code looks good. Check out the following link for retrieving what you want :
http://ricochen.wordpress.com/2012/02/28/example-sorted-set-functions-with-node-js-redis/
Added the code here from that link example in case it is ever removed.
var rc=require('redis').createClient();
var _=require('underscore');
rc.zincrby('myset', 1, 'usera');
rc.zincrby('myset', 5, 'userb');
rc.zincrby('myset', 3, 'userc');
rc.zrevrange('myset', 0, -1, 'withscores', function(err, members) {
// the resulting members would be something like
// ['userb', '5', 'userc', '3', 'usera', '1']
// use the following trick to convert to
// [ [ 'userb', '5' ], [ 'userc', '3' ], [ 'usera', '1' ] ]
// learned the trick from
// http://stackoverflow.com/questions/8566667/split-javascript-array-in-chunks-using-underscore-js
var lists=_.groupBy(members, function(a,b) {
return Math.floor(b/2);
});
console.log( _.toArray(lists) );
});
rc.quit();

Seems your code is right. The following is the syntax to get zrange.
without score:
redisClient.zrange(keyName,start,stop,function(err,result){
//result is array
// every index will give you member name
})
Ex :
redisClient.zrange("mySortedset",-1,-1,function(err,result){
//result is array
// every index will give you member name
})
with score:
redisClient.zrange(keyName,start,stop,'withscores',function(err,result){
//result is array
// here even index will hold member
// odd index will hold its score
})
Ex :
redisClient.zrange("mySortedset",-1,-1,'withscores',function(err,result){
//result is array
// here even index will hold member
// odd index will hold its score
})

I tried with the prior accepted answers but i could not get the result i want and later i tried with the following code and got appropriate result,
Original output:
[ 'player:522',
'19685',
'player:164',
'19594',
'player:807',
'19171',
'player:694',
'19165',
'player:905',
'19108',
'player:859',
'19087',
'player:432',
'18973',
'player:515',
'18831',
'player:163',
'18750',
'player:4',
'18552' ]
Expected output:
{
"player:522": "19685",
"player:164": "19594",
"player:807": "19171",
"player:694": "19165",
"player:905": "19108",
"player:859": "19087",
"player:432": "18973",
"player:515": "18831",
"player:163": "18750",
"player:4": "18552"
}
Solution:
redisClient.ZREVRANGE('daily', 1, 10, 'WITHSCORES', function(err, result) {
result = _.fromPairs(_.chunk(result, 2));
return res.status(200).json(result);
});

The right approach for versions ^2.0,
var args = [ key,to, from ];
redisClient.zrevrangebyscore(args,function(err,data){

Vanilla JS Solution
Redis call:
redisClient.zrange(keyName, start, stop, 'withscores', function(err, result) {
// result.reduce ... (See below)
}
Here is a Vanilla-JS solution that I came up with pretty quickly.
For me, personally, it does not make sense to import underscore or any other library to perform such an easy task:
result.reduce(function (a, c, i) {
var idx = i / 2 | 0;
if (i % 2) {
a[idx].score = c;
} else {
a[idx] = { id: c };
}
return a;
}, []);
Assuming this input:
['player1', 13, 'player2', 11, 'player4', 7, 'player3', 3, 'player5', 0]
This function yields:
[
{ id: 'player1', score: 13 },
{ id: 'player2', score: 11 },
{ id: 'player4', score: 7 },
{ id: 'player3', score: 3 },
{ id: 'player5', score: 0 }
]
Here is another one to transform the result into a two-dimensional array:
result.reduce(function (a, c, i) {
var idx = i / 2 | 0;
if (i % 2) {
a[idx].push(c);
} else {
a[idx] = [c];
}
return a;
}, []);
which produces the following array:
[
[ 'player1', 13 ],
[ 'player2', 11 ],
[ 'player4', 7 ],
[ 'player3', 3 ],
[ 'player5', 0 ]
]
One line lambda version:
result.reduce((a, c, i) => i % 2 ? (a[i / 2 | 0].data = c, a) : (a[i / 2 | 0] = { id: c }, a), []);

Vanilla JS reduce works well here.
const result = [
'player:522',
'19685',
'player:164',
'19594',
'player:807',
'19171',
'player:694',
'19165',
'player:905',
'19108',
'player:859',
'19087',
'player:432',
'18973',
'player:515',
'18831',
'player:163',
'18750',
'player:4',
'18552'
]
const map = result.reduce((map, k, i, res) => {
if (i % 2 !== 0) {
map[res[i - 1]] = Number(k);
}
return map;
}, {})
map is now:
{
'player:522': 19685,
'player:164': 19594,
'player:807': 19171,
'player:694': 19165,
'player:905': 19108,
'player:859': 19087,
'player:432': 18973,
'player:515': 18831,
'player:163': 18750.65468,
'player:4': 18552
}

var data = []
results.map((result, index) => {
if (index % 2 == 0) {
data.push(results[index] = { player: results[index], score: results[index+1] })
}
})
console.log(data)

Related

util.inspect Default depth is should be 20, but appears smaller

Code
Consider the following Node.js code:
const { inspect } = require('util');
const obj = { response: [ { webhooks: [ 1, 2, 3 ] } ] };
console.log(`Obj is ${obj}`);
console.log(`Obj is ${inspect(obj, { breakLength: Infinity })}`);
console.log(`Obj is ${inspect(obj, { breakLength: Infinity, depth: 20 })}`);
console.log(`Obj is ${inspect(obj, { breakLength: Infinity, depth: Infinity })}`);
Gives:
Obj is [object Object]
Obj is { response: [ { webhooks: [Array] } ] }
Obj is { response: [ { webhooks: [ 1, 2, 3 ] } ] }
Obj is { response: [ { webhooks: [ 1, 2, 3 ] } ] }
The Problem
According to the manual:
depth Specifies the number of times to recurse while formatting the object. This is useful for inspecting large complicated objects. To make it recurse up to the maximum call stack size pass Infinity or null. Default: 20.
As far as I understand it, the second console.log line should print the entire same string as the third, because the default for depth is 20. Alas, it prints [Array] instead of [ 1, 2, 3 ].
My Question
Why doesn't the default call behave like depth: 20?
Silly me.
On the latest versions, the default value is changed from 2 to 20. I was reading the documentation for v11 and used v8.

Is there a standard functional name for this function?

I'm sure this function is likely common ( or possibly achievable other ways ) but I'm not sure of what it'd be called. I'm thinking of a sliding window of a certain size :-
let slidingMap = (arr,size, f) => {
r = []
arr.reduce((acc, n) => {
let b = acc.concat(n);
if(b.length > size) {
b.shift();
}
if(b.length == size) {
r.push(f(b))
}
return b;
},[])
return r;
}
so given slidingMap([1,2,3,4,5,6], 2, b => b)
you'd get [ [ 1, 2 ], [ 2, 3 ], [ 3, 4 ], [ 4, 5 ], [ 5, 6 ] ]
and slidingMap([1,2,3,4,5,6], 3, b => b)
you'd get [ [ 1, 2, 3 ], [ 2, 3, 4 ], [ 3, 4, 5 ], [ 4, 5, 6 ] ]
or for calculating differences :-
slidingMap([1,2,3,7,5,6],2, b => b.reduceRight((a, n) => a? a-n : n))
you'd get [ 1, 1, 4, -2, 1 ]
or moving average :-
slidingMap([1,2,3,7,5,6],3, b => b.reduce((a, n) => a+n,0)/b.length)
you'd get [ 2, 4, 5, 6 ]
so, is there a commonly implemented function(s) that achieves this?
Update
Probablly better implemented as
let sliding = (arr,size) => {
r = []
arr.reduce((acc, n) => {
let b = acc.concat(n);
if(b.length > size) {
b.shift();
}
if(b.length == size) {
r.push(b)
}
return b;
},[])
return r;
}
then just use map
sliding([1,2,3,4,5],2).map(somefunc);
Or perhaps using zip and skip ( using lodash in this case )
let sliding = (arr, size) =>
_.zip(..._.range(size).map(i => arr.slice(i)))
.filter(a => !a.some(v => v == undefined))
only trick here is the zip will insert undefined when it has no match so they need to be filtered out.

CouchDB group view to keep string key and value

I have a view with documents in the form of {key:[year,month,day,string],value:int}:
{
rows:[
{
key: [
2016,
4,
30,
"String1"
],
value: 20
},
{
key: [
2016,
4,
30,
"String2"
],
value: 7
},
{
key: [
2016,
4,
30,
"String3"
],
value: 13
},{
key: [
2016,
5,
1,
"String1"
],
value: 10
},
{
key: [
2016,
5,
1,
"String4"
],
value: 12
},{
key: [
2016,
5,
2,
"String1"
],
value: 3
},
]}
From this I use startkey and endkey to get a range of values by date. My issue is then grouping the documents I get returned by the key string, and summing the value int. The rest of the key may or may not be present it does not matter. So far with group levels I have only been able to sum values per date key.
When rendered in a table I get something like:
What I want is:
So I ended up reducing in my controller with javascript like:
$scope.reduceMap = function (rows) {
var reducedMap = {};
var sortableArray = [];
for (var i = 0; i < rows.length; i++) {
var key = rows[i].key[3];
if (!reducedMap.hasOwnProperty(key)) {
reducedMap[key] = {key: key, value: rows[i].value};
} else {
reducedMap[key] = {key: key, value: rows[i].value + reducedMap[key].value};
}
}
for (var k in reducedMap) {
sortableArray.push(reducedMap[k]);
}
return sortableArray;
};
Since I asked for a CouchDB answer, I will leave this here but not accept it.
If you emit view's key as: string, year, month, day and use a built in reduce function _sum, then the following URL example gives you the desired result:
http://localhost:5984/text/_design/search/_view/by_text?startkey=["",2016,1,1]&endkey=[{},2016,1,1]&group_level=1
Your date search criteria is specified as normal, but the first part of the key is basically any string. Then grouping level 1 and reducing using sum gives you the count of string occurrences withing date range grouped by string.

How do I read a script array into duktape?

I'm new to duktape and trying to read a config
from a script file:
var config =
[
{ ready: true, name: "dev1", on: 8, off: 9 },
{ ready: true, name: "dev2", on: 10, off: 11 },
{ ready: true, name: "dev3", on: 18, off: 21 },
{ ready: true, name: "dev4", on: 13, off: 17 }
];
duktape has great documentation, but I can not seem to find
any example of what I am trying to accomplish.
I have managed to read a single dimension array. (Not sure if it is the best or proper way to to do it)
// var one_dim = [ "hello", "world", "single", "dimension", "array" ] ;
void init_one_dimension(void) {
duk_get_prop_string(ctx, -1, "one_dim");
if(duk_is_array(ctx, -1)) {
printf("Found array\n");
duk_enum(ctx, -1, DUK_ENUM_ARRAY_INDICES_ONLY);
while (duk_next(ctx, -1 , 0 )) {
duk_get_prop_index(ctx, -1, 0);
duk_get_prop_string(ctx, -4, duk_get_string(ctx, -1));
printf("%s\n", duk_get_string(ctx, -1));
show_stack(ctx, "STACK");
duk_pop(ctx); // get_prop_string
duk_pop(ctx); // get_prop_index
duk_pop(ctx); // duk_next
}
duk_pop(ctx); // duk_enum
duk_pop(ctx); // duk_get_prop_string
}
}
Multi-dimensional arrays escape me. Any help would be appreciated.
The 'config' object you have at the top, is not a multi-dimensional array but instead an array containing dictionaries. So with the enum code you have already, you just need to access the keys (ready, name, etc) like normal object properties.
duk_get_prop_string

Dojo AccordionContainer.addChild doesn't work for more than 2 children

I want to add programatically 4 children to dijit.layout.AccordionContainer. The script runs with no errors, but it only adds 2 children, no matter how I try to achieve this. From my debug using firebug it looks like the scripts stops after adding second child. I tried following suggestions from here, here and here, but I found no solution.
Some code:
AccordionContainer definition:
var listaWyjazdow = new dijit.layout.AccordionContainer({}, "target-lista-wyjazdow");
listaWyjazdow.startup();
aktualizujListeWyjazdow();
function to add 4 children to AccordionContainer:
function aktualizujListeWyjazdow(){
dojo.require("dijit.layout.AccordionPane");
var lista = dijit.byId('target-lista-wyjazdow');
lista.destroyDescendants();
var tablica = new dojo.data.ItemFileReadStore({
url: "logika/getJSON/getWyjazdy.php",
clearOnClose: true,
urlPreventCache: true
}).fetch({
query: {id: '*'},
sort: {attribute: 'data', descending: true},
start: 0,
count: 4,
onComplete: function(dane){
console.log(dane);
var ile = dane.length;
var i = 0;
var dzieci = new Array();
//this works for 2 children only:
for (i = 0; i < ile; i++){
var szczegoly = 'Klient: <strong>' + dane[i].klient + '</strong></br>';
szczegoly += 'Osoba wyjeżdżająca: <strong>' + dane[i].wyjezdzajacy + '</strong></br>';
dzieci[i] = new dijit.layout.AccordionPane({
id: "wyjazd" + i,
title: "Wyjazd: " + dane[i].data,
content: szczegoly
});
console.log(dane[i]);
console.log(i + ' - ' + ile);
lista.addChild(dzieci[i], 0);
lista.selectChild(dijit.byId('wyjazd' + i));
//console.log(lista);
}
//this works for 2 children only:
/*lista.addChild(dzieci[0]);
console.log(0);
lista.addChild(dzieci[1]);
console.log(1);
lista.addChild(dzieci[2]);
console.log(2);
lista.addChild(dzieci[3]);
console.log(3);*/
//this outputs all children:
/*console.log(dzieci[0]);
console.log(dzieci[1]);
console.log(dzieci[2]);
console.log(dzieci[3]);*/
//this works for 2 children only:
/*for (i = 0; i < ile; i++){
lista.addChild(dzieci[i]);
console.log(dzieci[i]);
}*/
}
});
}
console output (from firebug):
[Object { id=[1], etykieta=[1], data=[1], more...}, Object { id=[1], etykieta=[1], data=[1], more...}, Object { id=[1], etykieta=[1], data=[1], more...}, Object { id=[1], etykieta=[1], data=[1], more...}]
Object { id=[1], etykieta=[1], data=[1], more...}
0 - 4
Object { id=[1], etykieta=[1], data=[1], more...}
1 - 4
Any help would be greatly appreciated!
EDIT
a little update:
in my ItemFileReadStore object value returned by url is json:
{
"identifier": "id",
"label": "etykieta",
"items": [
{
"id": "1",
"etykieta": "Wyjazd0",
"data": "06-10-2011",
"wyjezdzajacy": "cblajszczak",
"idKlienta": "1",
"klient": "klient testowy",
"zadanieQS": null,
"dataKolejnegoWyjazdu": null,
"lacznyCzasWyjazdu": "0"
},
{
"id": "3",
"etykieta": "Wyjazd1",
"data": "15-11-2011",
"wyjezdzajacy": "cblajszczak",
"idKlienta": "1",
"klient": "klient testowy",
"zadanieQS": null,
"dataKolejnegoWyjazdu": null,
"lacznyCzasWyjazdu": "0"
},
{
"id": "5",
"etykieta": "Wyjazd2",
"data": "30-11-2011",
"wyjezdzajacy": "cblajszczak",
"idKlienta": "1",
"klient": "klient testowy",
"zadanieQS": null,
"dataKolejnegoWyjazdu": null,
"lacznyCzasWyjazdu": "0"
},
{
"id": "4",
"etykieta": "Wyjazd3",
"data": "24-11-2011",
"wyjezdzajacy": "cblajszczak",
"idKlienta": "2",
"klient": "hfhhfhd",
"zadanieQS": null,
"dataKolejnegoWyjazdu": null,
"lacznyCzasWyjazdu": "0"
}
]
}
dane[2] has following structure (taken from firebug):
_0 2
_RI true
_S Object { _arrayOfAllItems=[4], _arrayOfTopLevelItems=[4], _loadFinished=true, more...}
data ["30-11-2011"]
[other fields from json structure]
I have noticed that _S shown above contains whole dane array. And this dane contains another _S with whole dane array. And so on, recursively - could this be the problem?
I finally managed to solve my problem. In case anyone else encounters similar problem, the solution is to create container (AccordionContainer in this case) declaratively, not programmatically:
<div id="id" style="height:50%" dojoType="dijit.layout.AccordionContainer"></div>

Resources