I was trying to extract data from a JSON object using jsonpath package for following JSON structure -
[
{
"id": 1,
"images": [
{ "id": 1,"url": "http://url1.jpg" },
{ "id": 2,"url": "http://url2.jpg" }
]
},
{
"id": 2,
"images": [
{ "id": 3,"url": "http://url3.jpg" },
{ "id": 4,"url": "http://url4.jpg" }
]
},
{
"id": 3,
"images": [
{ "id": 5,"url": "http://url5.jpg" },
{ "id": 6,"url": "http://url6.jpg" }
]
}
]
In he above example, $..id json-path expression responds with following array -
[ 1, 1, 2, 2, 3, 4, 3, 5, 6 ]
What I have understood from the documentation is $..id is a recursive descent operator that recursively checks for the occurrence of id field in the specified array.
This is where I get the problem. I need an expression that simply checks for id in current object and avoids traversing recursively in images array.
So the expected output is -
[ 1, 2, 3 ]
I tried JSONPath Online Evaluator to verify the results.
Thanks.
According to the documentation of jsonpath they include
.. as Recursive descendant operator;
JSONPath borrows this syntax from E4X
$..* is used when you need to search in All memebers of JSON Structure.
So, if you want restrict the filter at the child you want you need to use $.*.
Here are the syntax
The code you want is:-
const fs = require('fs');
var jp = require('jsonpath');
let rawdata = fs.readFileSync('data.json');
let data = JSON.parse(rawdata);
var id = jp.query(data,'$.*.id');
console.log(id);
Output is
[1,2,3]
You can use the * operator which restricts the filter at the level you need.
To get it to do the thing that you want you would use:
$.*.id
and that will give you the output of:
[
1,
2,
3
]
But let's say you want the image specific id you would use:
$.*.images.*.id
which would give you the output of:
[
1,
2,
3,
4,
5,
6
]
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
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)
I'm fairly new to couchDB and the concept of views and reduces, and I could not find anything that would help me get my data in the format I want to consume it in.
My Data - Each set is it's own document
{
"_id": "2012-10-28",
"scores" : [
{
"bob": 3,
"dole": 5
}
]
}
{
"_id" : "2012-10-29",
"scores" : [
{
"bob": 3,
"dole": 6
}
]
}
I would like a view/reduce that returns something like:
"bob" : {
"2012-10-27": 3,
"2012-10-28": 3,
...
},
"dole": {
"2012-10-27": 5,
"2012-10-28": 6,
...
}
If this is not possible with my source data, I can reorganize it, but it will be tough.
Any help is greatly appreciated. I would also like to know of any good resources that explain the best practices for views and reduces.
Unless all the dates are known and you can hardcode them in the reduce function, I think it's a bit difficult to do what you need with map/reduce functions.
If it is ok to output something like:
{
"key": ["bob", "2012-10-27"],
"value": {"score": 3}
}
Then this map function should work:
var scoresMapFn = function (doc) {
var scores = doc.scores[0];
for (var k in scores) {
emit([k, doc._id], scores[k]);
}
};
Note that the structures of the original document could be optimised in my opinion. You have an array for scores but only have 1 element in it that is an object which has several keys for the names/players). This could be changed to:
{
"_id": "2012-10-28",
"scores": [
{
"name": "bob,
"score": 3
},
{
"name": "dole,
"score": 5
}
]
}
which would make it easier to manipulate.
Hope this helps a bit.