I have a dataset which looks like the following
{
"metadata":"d_meta_v_1.5.9",
"data": {
"a": {
"T": [
1652167964645,
1652168781684,
1652168781720
],
"V": [
1,
2,
3
]
},
"b": {
"T": [
1652167961657,
1652168781720,
1652168781818
],
"V": [
1,
3,
4
]
},
"c": {
"T": [
1652167960194,
1652168787377
],
"V": [
1,
3
]
}
}
}
I want to select the certain column and carry on the metadata also at the end. a part of this question is working in my perviou question here
How can I get my desired output ?
Metadata, Time, a, b
d_meta_v_1.5.9, <Time>, <value of _a>, < value of b>
d_meta_v_1.5.9, <Time>, <value of _a>, < value of b>
d_meta_v_1.5.9, <Time>, <value of _a>, < value of b>
let requested_columns = dynamic(["a","b"]);
datatable(doc:dynamic)
[
dynamic
(
{
"metadata":"d_meta_v_1.5.9",
"data": {
"a": {
"T": [
1652167964645,
1652168781684,
1652168781720
],
"V": [
1,
2,
3
]
},
"b": {
"T": [
1652167961657,
1652168781720,
1652168781818
],
"V": [
1,
3,
4
]
},
"c": {
"T": [
1652167960194,
1652168787377
],
"V": [
1,
3
]
}
}
}
)
]
| project metadata = doc.metadata, data = doc.data
| mv-expand data = data
| extend key = tostring(bag_keys(data)[0])
| where key in (requested_columns)
| mv-expand T = data[key].T to typeof(long), V = data[key].V to typeof(long)
| evaluate pivot(key, take_any(V), metadata, T)
| order by T asc
metadata
T
a
b
d_meta_v_1.5.9
1652167961657
1
d_meta_v_1.5.9
1652167964645
1
d_meta_v_1.5.9
1652168781684
2
d_meta_v_1.5.9
1652168781720
3
3
d_meta_v_1.5.9
1652168781818
4
Fiddle
Related
Suppose I have an object like:
{
"a": 1,
"b": 2,
"c": [
{
"d": 1,
"e": 2
},
{
"d": 2,
"e": 3
}
]
}
and I wish to extract only a set of keys (which are possibly nested), like .a and .c[].d, giving us the following output:
{
"a": 1,
"c": [
{
"d": 1
},
{
"d": 2
}
]
}
How would I go about doing that?
Here are two possible ways to do it:
Explicitly extracting the keys (like in this question), e.g.:
$ jq '{a, c: .c[] | {d}}' test.json
{
"a": 1,
"c": {
"d": 1
}
}
{
"a": 1,
"c": {
"d": 2
}
}
which works but can get ugly very quickly if you try to use it with long keys or deeply nested sub-objects.
Note that selecting paths that don't exist will result in null:
$ jq '{a, c: .c[] | {f}}' test.json
{
"a": 1,
"c": {
"f": null
}
}
{
"a": 1,
"c": {
"f": null
}
}
Implementing pick function to filter an object for specific keys:
def pick(paths):
. as $root |
reduce path(paths) as $path
({}; setpath($path; $root | getpath($path)));
Resulting in:
$ jq "$(cat query.jq)"' pick(.a, .c[].f, .c[].d)' test.json
{
"a": 1,
"c": [
{
"f": null,
"d": 1
},
{
"f": null,
"d": 2
}
]
}
If we'd like non-existent paths to be omitted instead of set to null, we can add haspath function to check if a path exists inside an object like so:
def haspath($path):
def h:
. as [$json, $p]
| (($p|length)==0) or
($json | (has($p[0]) and ( [getpath([$p[0]]), $p[1:] ] | h)));
[., $path] | h;
def pick(paths):
. as $root |
reduce path(paths) as $path
({}; if $root|haspath($path) then . + setpath($path; $root | getpath($path)) else . end);
Resulting in:
$ jq "$(cat query_haspath.jq)"' pick(.a, .c[].f, .c[].d)' test.json
{
"a": 1,
"c": [
{
"d": 1
},
{
"d": 2
}
]
}
I have a timeseries data which looks like follows
"data": {
"a": {
"T": [
1652167964645,
1652168781684,
1652168781720,
1652169266156,
1652169267146,
1652169272796,
1652169299338
],
"V": [
1,
2,
3,
10,
6,
1252,
1555
]
},
"b": {
"T": [
1652167961657,
1652168781720,
1652168781818,
1652168787377,
1652168835734,
1652169266108,
1652169266125,
1652169272798,
1652169299328
],
"V": [
1,
3,
4,
6,
12,
15,
16,
17,
1
]
},
"c": {
"T": [
1652167960194,
1652168787377,
1652169266108,
1652169272798,
1652169299328
],
"V": [
1,
3,
17,
18,
1
]
}}
inside the sub documents there are time and values
I can process the data in total. but if I want tp process only two sub document how can i do that ?
I can project like following
| project data["a"],data["b"] but then I can not process the time. how can i accomplish it ?
Expected output:
One column with time, and other column ( i.e a, b ) for the values
Time , A , B
0:55, 1,2
let requested_columns = dynamic(["a","b"]);
datatable(data:dynamic)
[
dynamic
(
{
"a": {
"T": [
1652167964645,
1652168781684,
1652168781720,
1652169266156,
1652169267146,
1652169272796,
1652169299338
],
"V": [
1,
2,
3,
10,
6,
1252,
1555
]
},
"b": {
"T": [
1652167961657,
1652168781720,
1652168781818,
1652168787377,
1652168835734,
1652169266108,
1652169266125,
1652169272798,
1652169299328
],
"V": [
1,
3,
4,
6,
12,
15,
16,
17,
1
]
},
"c": {
"T": [
1652167960194,
1652168787377,
1652169266108,
1652169272798,
1652169299328
],
"V": [
1,
3,
17,
18,
1
]
}
}
)
]
| mv-expand data
| extend key = tostring(bag_keys(data)[0])
| where key in (requested_columns)
| mv-expand T = data[key].T to typeof(long), V = data[key].V to typeof(long)
| evaluate pivot(key, take_any(V), T)
| order by T asc
T
a
b
1652167961657
1
1652167964645
1
1652168781684
2
1652168781720
3
3
1652168781818
4
1652168787377
6
1652168835734
12
1652169266108
15
1652169266125
16
1652169266156
10
1652169267146
6
1652169272796
1252
1652169272798
17
1652169299328
1
1652169299338
1555
Fiddle
I want to loop over a JSON array like this:
[
{
"id": 1,
"count" : 30
},
{
"id": 2,
"count" : 10
},
{
"id": 3,
"count" : 5
},
{
"id": 4,
"count" : 15
}
]
So I would like to have a query to project a TotalCount which would basically go over the json array and sum all the count values(30+10+5+15) and display as a new column
You can use mv-apply to do so.
For example:
datatable(d: dynamic) [
dynamic([
{
"id": 1,
"count": 30
},
{
"id": 2,
"count": 10
},
{
"id": 3,
"count": 5
},
{
"id": 4,
"count": 15
}
]),
dynamic([
{
"id": 1,
"count": 3
},
{
"id": 2,
"count": 1
},
{
"id": 3,
"count": 50
},
{
"id": 4,
"count": 1
}
]),
]
| mv-apply d on (
summarize result = sum(tolong(d['count']))
)
result
60
55
I'm trying to read a JSON object with has nested lists. Which looks like this:
[{
"id": 70070037001,
"text": "List 1",
"isleaf": 0,
"children": [
{
"oid": 100,
"text": "Innerlistobject100",
"isleaf": 0,
"children": [
{
"sid": 1000,
"text": "Innerlistobject1000",
"isleaf": 1
},
{
"sid": 2000,
"text": "Innerlistobject2000",
"isleaf": 1
}
]
},
{
"oid": 200,
"text": "Innerlistobject200",
"isleaf": 0,
"children": [
{
"sid": 1000,
"text": "Innerlistobject1000",
"isleaf": 1
},
{
"sid": 2000,
"text": "Innerlistobject2000",
"isleaf": 1
}
]
}
]
}]
ref: https://sourceforge.net/p/pljson/discussion/935365/thread/375c0293/ - where the person is creating the object, but I want to do the opposite and read it.
Do I have to iterate like this (note name is children within children):
Declare
l_Children_List json_list;
JSON_Obj json;
l_Child_JSON_Obj json;
Begin
IF (JSON_Obj.exist ('children')) THEN
IF (JSON_Obj.get ('children').is_array)
l_Children_List := json_list (JSON_Obj.get ('children'));
FOR i IN 1 .. l_Children_List.COUNT
IF (JSON_Obj.exist ('children')) THEN
IF (JSON_Obj.get ('children').is_array)
l_Children_List := json_list (JSON_Obj.get ('children'));
FOR i IN 1 .. l_Children_List.COUNT
jSON_child_val := l_Children_List.get (i);
l_Child_JSON_Obj := json (jSON_child_val );
LOOP
End If;
LOOP
End If;
End;
with json_example as (
select '{
"id": 70070037001,
"text": "List 1",
"isleaf": 0,
"children": [
{
"oid": 100,
"text": "Innerlistobject100",
"isleaf": 0,
"children": [
{
"sid": 1000,
"text": "Innerlistobject1000",
"isleaf": 1
},
{
"sid": 2000,
"text": "Innerlistobject2000",
"isleaf": 1
}
]
},
{
"oid": 200,
"text": "Innerlistobject200",
"isleaf": 0,
"children": [
{
"sid": 1000,
"text": "Innerlistobject1000",
"isleaf": 1
},
{
"sid": 2000,
"text": "Innerlistobject2000",
"isleaf": 1
}
]
}
]
}' as json_document
from dual
)
SELECT tab.*
FROM json_example a
join json_table (a.json_document, '$'
COLUMNS
(id NUMBER PATH '$.id'
,text VARCHAR2(50) PATH '$.text'
,isleaf NUMBER PATH '$.isleaf'
,NESTED PATH '$.children[*]'
COLUMNS
(oid NUMBER PATH '$.oid'
,otext VARCHAR2(150) PATH '$.text'
,oisleaf NUMBER PATH '$.isleaf'
,NESTED PATH '$.children[*]'
COLUMNS
(sid NUMBER PATH '$.sid'
,stext VARCHAR2(250) PATH '$.text'
,sisleaf NUMBER PATH '$.isleaf'
)
)
)
) tab on 1=1
I have some json data that looks like:
{
"p": {
"d": {
"a" : {
"r": "foo",
"g": 1
},
"b": {
"r": "bar",
"g": 2
}
},
"c": {
"e": {
"r": "baz",
"g": 1
}
},
...
}
}
I want something like:
{
"d": [
"a",
"b"
],
"c": [
"e"
]
}
I can get the list of keys on the first level under "p" with jq '.p|keys', and the structure and keys on the second level with jq '.p|map(.|keys)', but I can't figure out how to combine it.
Use map_values instead of map to map the values of a JSON object while preserving the keys:
jq '.p | map_values(keys)'
On jq versions lower than 1.5, map_values is not defined: instead, you can use []|=:
jq '.p | . []|= keys'
In general
Top level keys:
curl -s https://crates.io/api/v1/crates/atty | jq '. |= keys'
[
"categories",
"crate",
"keywords",
"versions"
]
Two levels of keys:
curl -s https://crates.io/api/v1/crates/atty | jq '.| map_values(keys)'
{
"crate": [
"badges",
"categories",
"created_at",
"description",
"documentation",
"downloads",
"exact_match",
"homepage",
"id",
"keywords",
"links",
"max_version",
"name",
"newest_version",
"recent_downloads",
"repository",
"updated_at",
"versions"
],
"versions": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16
],
"keywords": [
0,
1,
2
],
"categories": []
}
Method versions
topLevelJsonKeys() {
curl -s $1 | jq '. |= keys'
# EXAMPLE:
# topLevelJsonKeys https://crates.io/api/v1/crates/atty
}
topLevelJsonKeys2() {
curl -s $1 | jq '.| map_values(keys)'
# EXAMPLE:
# topLevelJsonKeys2 https://crates.io/api/v1/crates/atty
}
Here is a solution which uses reduce and setpath
.p
| reduce keys[] as $k (
.
; setpath([$k]; .[$k] | keys)
)