simple jq filter has null results - jq

I'm using the filter
[.bar_1.baz_a, .bar_1.baz_b, .bar_2.qux_1,.bar_2.qux_2]
on the following JSON and it's returning four nulls instead of two lines each having four elements of nonsense data. This is my first attempt at a filter, what concept am I not comprehending?
{
"version": "0.1",
"foos": [
{
"bar_1": {
"baz_a": 673396201,
"baz_b": "dfgsfg"
},
"bar_2": {
"qux_1": "ghjhj",
"qux_2": "Q"
}
},
{
"bar_1": {
"baz_a": 674567484,
"baz_b": "tyutyj"
},
"bar_2": {
"qux_1": "bnmn",
"qux_2": "Z"
}
}
]
}

The root object doesn't have keys bar1 and bar2; those occur in the objects in the array assigned to the name foos. Compare your filter to
jq '.foos[] | [.bar_1.baz_a, .bar_1.baz_b, .bar_2.qux_1,.bar_2.qux_2]' tmp.json

Related

Remove multiple entries from an array of objects using jq

I have the following json and want to remove multiple entries from the ebooks array if they are not in the following array ["Pascal", "Python"] (will eventually be dynamic array, this is just for example)
{
"eBooks":[
{
"language":"Pascal",
"edition":"third"
},
{
"language":"Python",
"edition":"four"
},
{
"language":"SQL",
"edition":"second"
}
]
}
was hoping to do something like this, which if it worked would delete last one containing the SQL because it's not in the array, but this doesn't work
jq '.ebooks[] | select ( .language | in(["Pascal", "Python"]))' ebooks.json
You're almost there. Use del, IN and a capital B in eBooks :)
jq 'del(.eBooks[] | select(.language | IN("Pascal", "Python")))' ebooks.json
{
"eBooks": [
{
"language": "SQL",
"edition": "second"
}
]
}
Demo

Terraform: Add item to a DynamoDB Table

What is the correct way to add tuple and key-pair values items to a DynamoDB database via Terraform?
I am trying like this:
resource "aws_dynamodb_table_item" "item" {
table_name = aws_dynamodb_table.dynamodb-table.name
hash_key = aws_dynamodb_table.dynamodb-table.hash_key
for_each = {
"0" = {
location = "Madrid"
coordinates = [["lat", "40.49"], ["lng", "-3.56"]]
visible = false
destinations = [0, 4]
}
}
item = <<ITEM
{
"id": { "N": "${each.key}"},
"location": {"S" : "${each.value.location}"},
"visible": {"B" : "${each.value.visible}"},
"destinations": {"L" : [{"N": "${each.value.destinations}"}]
}
ITEM
}
And I am getting the message:
each.value.destinations is tuple with 2 elements
│
│ Cannot include the given value in a string template: string required.
I also have no clue on how to add the coordinates variable.
Thanks!
List should be something like that :
"destinations": {"L": [{ "N" : 1 }, { "N" : 2 }]}
You are trying to pass
"destinations": {"L": [{ "N" : [0,4] }]}
Also you are missing the last } in destinations key
TLDR: I think the problem here is that you are trying to put L(N) - i.e. a list of numeric values, while your current Terraform code tries to put all the destinations into one N/number.
Instead of:
[{"N": "${each.value.destinations}"}]
you need some iteration over destinations and building a {"N": ...} of them.
"destinations": {"NS": ${jsonencode(each.value.destinations)}}
Did the trick!

Add values to a JSON array if outer array's name == 'something'

I'm passing a JSON object to jq and want to add extra objects to an inner array ('accessories') if its parent array ('platforms') matches a certain name.
Here's my source JSON:
{
"bridge": {
"name": "Homebridge",
"port": 51395
},
"accessories": [],
"platforms": [
{
"name": "Config",
"port": 8581,
"platform": "config"
},
{
"platform": "homebridge-cbus.CBus",
"name": "CBus",
"client_ip_address": "127.0.0.1",
"accessories": [
{
"values": "existing"
}
]
}
]
}
This works beautifully:
jq '.platforms[1].accessories += [{ "values" : "NEW" }]'
... but of course it's poor form to expect platforms[1] to always the be array I want to append to, so I set about trying to form the right syntax for a search or if/then/else to only act on the .name of the appropriate one.
I thought this was my solution:
jq '.platforms[] | if ( .name=="CBus" ) then .accessories += [{ "values" : "NEW" }] else . end'
... until I realised it was only passing the 'platforms' through and eating the 'bridge' object and empty outer 'accessories' array, which I need to retain.
My issue looks to be similar to JQ | Updating array element selected by `select`, but I've tried LOTS of combinations but just can't break through.
Edit: Here's the correct JQPlay I've been working with:
https://jqplay.org/s/dGDswqAEte
Thanks for any help.
That's a good attempt. The key here is to use the select() function to identify the object you are going to update and overwrite the overall array using |= operator, i.e.
.platforms |= ( map(select(.name == "CBus").accessories += [{ "values" : "NEW" }] ) )
For the snippet in your jq-play link (now removed), you need to do
.gcp_price_list."CP-COMPUTEENGINE-OS"
|= with_entries(select(.value.cores == "shared").value.cores = "0.5")
Or if you want to be even more specific, and keep the entry in gcp_price_list configurable, do
.gcp_price_list |=
with_entries (
select(.key == "CP-COMPUTEENGINE-OS").value |=
with_entries(
select(.value.cores == "shared").value.cores = "0.5") )

Jsonpath - filter at child level to get parent attribute

Is there any way to extract "a" value by filtering on "d" in the following json?
[
{
"a":1,
"b":{ "c":11,"d":12 }
},
{
"a":2,
"b":{ "c":21,"d":22}
}
]
$..[?(#.b.d == 12)].a
above expression can solve this

Query to get exact matches of Elastic Field with multile values in Array

I want to write a query in Elastic that applies a filter based on values i have in an array (in my R program). Essentially the query:
Matches a time range (time field in Elastic)
Matches "trackId" field in Elastic to any value in array oth_usr
Return 2 fields - "trackId", "propertyId"
I have the following primitive version of the query but do not know how to use the oth_usr array in a query (part 2 above).
query <- sprintf('{"query":{"range":{"time":{"gte":"%s","lte":"%s"}}}}',start_date,end_date)
view_list <- elastic::Search(index = "organised_recent",type = "PROPERTY_VIEW",size = 10000000,
body=query, fields = c("trackId", "propertyId"))$hits$hits
You need to add a terms query and embed it as well as the range one into a bool/must query. Try updating your query like this:
terms <- paste(sprintf("\"%s\"", oth_usr), collapse=", ")
query <- sprintf('{"query":{"bool":{"must":[{"terms": {"trackId": [%s]}},{"range": {"time": {"gte": "%s","lte": "%s"}}}]}}}',terms,start_date,end_date)
I'm not fluent in R syntax, but this is raw JSON query that works.
It checks whether your time field matches given range (start_time and end_time) and whether one of your terms exact matches trackId.
It returns only trackId, propertyId fields, as per your request:
POST /indice/_search
{
"_source": {
"include": [
"trackId",
"propertyId"
]
},
"query": {
"bool": {
"must": [
{
"range": {
"time": {
"gte": "start_time",
"lte": "end_time"
}
}
},
{
"terms": {
"trackId": [
"terms"
]
}
}
]
}
}
}

Resources