Using jq to get arrays where a key within the array is equal to a specific value? - jq

I have been practicing with jq play to try to get all the arrays in a list where website is == "google" and create another json list from that.
https://jqplay.org/s/DKNC2mhOLq
jq: error (at :18): Cannot index array with string "website"
exit status 5
{
"items": [
{
"name":"name1",
"id":"1",
"website":"google"
},
{
"name":"name1",
"id":"1",
"website":"google"
},
{
"name":"name1",
"id":"2",
"website":"jingle"
}
]
Desired output:
[
{
"name":"name1",
"id":"1",
"website":"google"
},
{
"name":"name1",
"id":"1",
"website":"google"
}
]
how can I loop through arrays in a list and look for specific values for specific keys? Thanks for any help or ideas you can provide. I am a begginer with JSON and jq.

Enclose the select with a map, as you want to apply the filter to each array item individually while retaining the surrounding array structure.
jq '.items | map(select(.website == "google"))'
[
{
"name": "name1",
"id": "1",
"website": "google"
},
{
"name": "name1",
"id": "1",
"website": "google"
}
]
Demo

Related

jq: filter array and project other field

Here my document:
[
{
"id": "9f0e27fe-3b8f-4857-8e1d-e57e7a3f4c31",
"identifier": [
{
"system": {
"value": "urn:oid:1.3.6.1.4.1.19126.3"
},
"value": {
"value": "Y3454867M"
}
},
{
"system": {
"value": "urn:oid:2.16.724.4.9.10.2"
},
"value": {
"value": "108505134"
}
}
]
}
]
I need to pick only .identifier[where .system.value == "urn:oid:1.3.6.1.4.1.19126.3"] and project .identifier.value.value.
Desired output:
[
{
"id": "9f0e27fe-3b8f-4857-8e1d-e57e7a3f4c31",
"identifier": "Y3454867M"
}
]
I've been playing with map and select but I don't quite figure out what's the right way to get it.
Any ideas?
This approach uses first to get the first result, in case there is more than one array item matching the criteria.
jq --arg v "urn:oid:1.3.6.1.4.1.19126.3" '
map(.identifier |= first(.[] | select(.system.value == $v).value.value))
'
[
{
"id": "9f0e27fe-3b8f-4857-8e1d-e57e7a3f4c31",
"identifier": "Y3454867M"
}
]
Demo
Right on the money with the good ol' select tool, since you need data from an arbitrary index. I fumbled a bit before I unwrapped the inner array that gets piped to my select.
jq -r '.[] | [{id: .id, identifier: .identifier | .[] | select(.system.value | contains("urn:oid:1.3.6.1.4.1.19126.3")) | .value.value }]'
Still new to jq myself, so any feedback is welcome.

Gremlin Query (JSON Output) using tree

Query:
g.withSack(0).V().hasLabel('A').has('label_A','A').union(__.emit().repeat(sack(sum).by(constant(1)).in()),emit().repeat(sack(sum).by(constant(-1)).out())).project('level','properties').by(sack()).by(tree().by(valueMap().by(unfold())).unfold())
Output:
{
"level": 1,
"properties": {
"key": {
"label_A": "A"
},
"value": {
"{label_A=A}": {}
}
}
},
{
"level": 2,
"properties": {
"key": {
"label_A": "A"
},
"value": {
"{label_A=A}": {}
}
}
}
}
Getting keys in json format but not values. Please suggest changes in query to acheive the values in json format.
The tree() step returns a tree structure in the form of a Map of Map instances essentially so the output is about what you can expect. In this case, I wonder if you need to use tree() and could instead get by with path() as it seems like it accomplishes the same result without the added structure:
g.withSack(0).
V().hasLabel('A').has('label_A','A').
union(__.emit().repeat(sack(sum).by(constant(1)).in()),
emit().repeat(sack(sum).by(constant(-1)).out())).
project('level','properties').
by(sack()).
by(path().by(elementMap()))

Get Key from value using jq [duplicate]

This question already has an answer here:
How do I extract a key with jq based on its child values
(1 answer)
Closed 2 years ago.
Dear members of support,
I need to get a key by value. Specifically, I need to get the key 2 search by value AWS2. I am trying to use this example [1] without success. Could you help, please?
{
"1": ["AWS1"],
"2": ["AWS2"],
"3": ["AWS3"]
}
The entire json is this one
{
"ARN": "xxxxx",
"Name": "xxxx",
"Description": "xxxx",
"KmsKeyId": "xxxx",
"RotationEnabled": true,
"RotationLambdaARN": "arggg",
"RotationRules": {
"AutomaticallyAfterDays": 30
},
"LastRotatedDate": "2020-05-27T12:05:56.061000-03:00",
"LastChangedDate": "2020-05-27T13:05:34.807000-03:00",
"LastAccessedDate": "2020-05-26T21:00:00-03:00",
"Tags": [
{
"Key": "aws:cloudformation:stack-name",
"Value": "medusa-monitoring-alerts-role"
},
{
"Key": "aws:cloudformation:logical-id",
"Value": "xxx"
},
{
"Key": "Team",
"Value": "xxx xxx"
},
{
"Key": "aws:cloudformation:stack-id",
"Value": "xxx"
}
],
"VersionIdsToStages": {
"1": [
"AWS1"
],
"2": [
"AWS2"
],
"3": [
"AWS3"
]
}
}
I am trying
.VersionIdsToStages|map_values(select(contains(["AWS2"]))) | keys[0]
without sucess.
[1] https://github.com/stedolan/jq/issues/60
You could use the following :
map_values(select(contains(["AWS2"]))) | keys
map_values lets you iterate on the key/value pairs of an object and transform them. Here we use it to remove the key/value pairs with values that do not contain "AWS2". Then we simply use keys to retrieve the keys of those pairs from the transformed object.
If you can assume that only a single value will ever match, you can add a [0] to the end to retrieve the key only rather than an array containing it.
You can try it here.

How do I use a value as a key reference in jq?

I have two JSON files as follows.
One contains a mapping of project to owners.
owners.json
{
"Project1": "owner1",
"Project2": "owner2"
}
The second contains a list of projects with extra information:
projects.json
[
{
"name": "Project1",
"base": "A"
},
{
"name": "Project2",
"base": "B"
}
]
I'd like to use JQ to merge the two files to look like the following:
output.json
[
{
"name": "Project1",
"owner": "owner1",
"base": "A"
},
{
"name": "Project2",
"owner": "owner2",
"base": "B"
}
]
My first thought was to try something like this (assuming projects.json is fed on stdin):
jq --slurpFile owners owners.json '.name as $n | [.[] | {name, base, owner: $owners[0].$n}]'
This gives a syntax error relating to the $n in $owners[0].$n. What's the right way to do this in JQ?
Thanks!
You need to wrap variable references in square brackets for indexing objects with them. Even though you corrected that your script wouldn't work as arrays can't be indexed with strings (.name as $n part).
And don't bother with slurpfile, there are simpler ways.
$ jq 'input as $owners | map(.owner = $owners[.name])' projects.json owners.json
[
{
"name": "Project1",
"base": "A",
"owner": "owner1"
},
{
"name": "Project2",
"base": "B",
"owner": "owner2"
}
]

CosmosDB, help flatten and filter by nested array

I'm trying to flatten and filter my json data that is in a CosmosDB.
The data looks like below and I would like to flatten everything in the array Variables and then filter by specific _id and Timestamp inside of the array:
{
"_id": 21032,
"FirstConnected": {
"$date": 1522835868346
},
"LastUpdated": {
"$date": 1523360279908
},
"Variables": [
{
"_id": 99999,
"Values": [
{
"Timestamp": {
"$date": 1522835868347
},
"Value": 1
}
]
},
{
"_id": 99998,
"Values": [
{
"Timestamp": {
"$date": 1523270312001
},
"Value": 8888
}
]
}
]
}
If you want to flatten data from the Variables array with properties from the root object you can query your collection like this:
SELECT root._id, root.FirstConnected, root.LastUpdated, var.Values
FROM root
JOIN var IN root.Variables
WHERE var._id = 99998
This will result into:
[
{
"_id": 21032,
"FirstConnected": {
"$date": 1522835868346
},
"LastUpdated": {
"$date": 1523360279908
},
"Values": [
{
"Timestamp": {
"$date": 1523270312001
},
"Value": 8888
}
]
}
]
If you want to even flatten the Values array you will need to write something like this:
SELECT root._id, root.FirstConnected, root.LastUpdated,
var.Values[0].Timestamp, var.Values[0]["Value"]
FROM root
JOIN var IN root.Variables
WHERE var._id = 99998
Note that CosmosDB considers "Value" as a reserved keyword and you need to use an escpape syntax. The result for this query is:
[
{
"_id": 21032,
"FirstConnected": {
"$date": 1522835868346
},
"LastUpdated": {
"$date": 1523360279908
},
"Timestamp": "1970-01-01T00:00:00Z",
"Value": 8888
}
]
Check for more details https://learn.microsoft.com/en-us/azure/cosmos-db/sql-api-sql-query#Advanced
If you're only looking for filtering by the nested '_id' property then you could use ARRAY_CONTAINS w/ the partial_match argument set to true. The query would look something like this:
SELECT VALUE c
FROM c
WHERE ARRAY_CONTAINS(c.Variables, {_id: 99998}, true)
If you also want to flatten the array, then you could use JOIN
SELECT VALUE v
FROM v IN c.Variables
WHERE v._id = 99998

Resources