Pass array index into children entries with jq - jq

If you think the title of this post is off, so do I. I'm happy to reformulate but it's hard to explain.
Given this:
[
{
"A": "a",
"B": "b",
"C": "c"
},
{
"D": "d",
"E": "e"
}
]
I want this:
[
{ index: 0, key: "A", value: "a" },
{ index: 0, key: "B", value: "b" },
{ index: 0, key: "C", value: "c" },
{ index: 1, key: "D", value: "d" },
{ index: 1, key: "E", value: "e" }
]
Now whether it's a single array in the end or something else, it doesn't really matter.
What I'm really looking for is to transform those elements in the input array into key-value pairs, and add the index of that element from the array.
So the first object in the array is "index: 0", second is "index: 1", etc.
I can get the index from the array just fine:
jq 'to_entries | .[]' sample.json
which gives me:
{
"key": 0,
"value": {
"A": "a",
"B": "b",
"C": "c"
}
}
{
"key": 1,
"value": {
"D": "d",
"E": "e"
}
}
And I can get the key-value pairs just fine too:
jq 'to_entries | .[] | .value | to_entries' sample.json
which gives me:
[
{
"key": "A",
"value": "a"
},
{
"key": "B",
"value": "b"
},
{
"key": "C",
"value": "c"
}
]
[
{
"key": "D",
"value": "d"
},
{
"key": "E",
"value": "e"
}
]
but I can't figure out how to combine the two.

This gives expected result :
jq 'to_entries|map({index:.key}+(.value|to_entries[]))' sample.json

Related

How can I spread array elements in parent object by jq?

I want to transform following type of json obj
[
{
"A": "a",
"Tags": [
{ "key":"x", "value":0},
{ "key":"y", "value":1},
]
},
{...}
]
to this, including Tags list on top
[
{
"A": "a",
"x": 0,
"y": 1
},
{...}
]
I try to use JQ but without result.
map(. + (.Tags | from_entries) | del(.Tags))
Will map() over all the objects in the array and:
Convert .Tags to an object using from_entries
This is added to the original object (. + ())
Delete the original .Tags
Output:
[
{
"A": "a",
"x": 0,
"y": 1
}
]
Online Demo

How to return an array from `capture` with `global` filter in `jq`

Given the following input:
{
"text": "a1\nb2"
}
How do I get the following output:
[
{
"letter": "a",
"number": 1
},
{
"letter": "b",
"number": 2
}
]
I've tried using capture with the "g" flag, but this yields two documents instead of a single document with an array of captured inputs:
$ echo '{
"text": "a1\\nb2"
}' | jq '.text | capture("(?<letter>[a-z])(?<number>[0-9])";"g")'
{
"letter": "a",
"number": "1"
}
{
"letter": "b",
"number": "2"
}
Here is a link to the jqplay example.
Why not just wrap the capture in a new array:
.text | [ capture("(?<letter>[a-z])(?<number>[0-9])";"g") ]
JqPlay

query for access selective array items from COSMOS db

I need to fetch some selective array items from following array in cosmos db collection.
"details": [
{
"name": "a",
"roll_no": 100,
"sub":"maths",
"class":"3"
},
{
"name": "b",
"roll_no":"512",
"sub":"eng",
"class":"5"
},
{
"name": "c",
"roll_no":"512",
"sub":"eng",
"class":"7"
}
and so on
Desired output is:
"details": [
{
"name": "a",
"roll_no": 100,
},
{
"name": "b",
"roll_no":"512",
},
{
"name": "c",
"roll_no":"512",
}
and so on
How can I write query for the same in cosmosb db?
Using a subquery and the ARRAY function will work:
SELECT c.id, ARRAY(SELECT d.name, d.roll_no FROM d in c.details) AS details
FROM c

JQ Group By by Key, Merge Value, then Flatten Object

With the following inputs:
# file1.json
{
"uid": "1",
"name": "jack"
}
{
"uid": "2",
"name": "jill"
}
# file2.json
{
"fid": "a",
"file": "sample1.txt",
"uid": "1"
}
{
"fid": "b",
"file": "sample2.txt",
"uid": "1"
}
{
"fid": "c",
"file": "sample3.txt",
"uid": "2"
}
How do I go about inserting the name key-value pair to the object in the file2.json. The output I'm trying to get is as follows:
{
"fid": "a",
"file": "sample1.txt",
"uid": "1",
"name": "jack"
}
{
"fid": "b",
"file": "sample2.txt",
"uid": "1",
"name": "jack"
}
{
"fid": "c",
"file": "sample3.txt",
"uid": "2",
"name": "jill"
}
Solutions posted on merge json objects with jq and join two json files based on common key with jq utility or alternative way from command line both seems to only return the last matching pair. See below.
{"uid":"1","name":"jack","fid":"b","file":"sample2.txt"}
{"uid":"2","name":"jill","fid":"c","file":"sample3.txt"}
You will need to "slurp" file1.json, e.g. by invoking jq as follows:
jq -n -f merge.jq --slurpfile file1 file1.json file2.json
where merge.jq contains:
INDEX($file1[]; .uid) as $dict
| inputs
| . + $dict[.uid]
def INDEX
If your jq does not have INDEX/2, then simply add its def:
def INDEX(stream; idx_expr):
reduce stream as $row ({}; .[$row|idx_expr|tostring] = $row);

Cosmos DB SQL API query for children of nested objects

I would like to find a better way to search for if documents in a collection have a property with more than 0 elements in the array, i.e. anything that isn't empty.
such as: select * from c where c.property = 'x' and array_length(c.child) > 0 and array_length(c.child.grandchild) > 0
The first arraylength works. Adding the second with just this dot notation doesn't work as I read somewhere else. How can I ensure that I can accomplish this. The grandchild will be anywhere from 0 to many number where it has a greater array length than 0.
Please let me know if more clarification is needed.
Please use below sql :
SELECT distinct c.id,c.name,c.child FROM c
join child in c.child
where array_length(c.child) > 0
and array_length(child.grandchild) > 0
My sample documents:
[
{
"id": "1",
"name": "Jay",
"child": [
{
"name": "A",
"grandchild": [
{
"name": "A1"
},
{
"name": "A2"
}
]
},
{
"name": "B",
"grandchild": [
{
"name": "B1"
},
{
"name": "B2"
}
]
}
]
},
{
"id": "2",
"name": "Tom",
"child": [
{
"name": "A",
"grandchild": []
},
{
"name": "B",
"grandchild": []
}
]
}
]
Hope it helps you.

Resources