Remove specific key and value from nested json array in PostgreSQL column - sql

I have a json object field in PostgreSQL in mytable.fields as below
{
"a": "1",
"b": [
{
"c": 2,
"d": 3
},
{
"c": 4,
"d": 5
},
{
"c": 6,
"d": 7
}
]
}
How can I delete all "c" key and value pairs like as below?
I found other StackOverflow solutions that remove the whole object, but I couldn't find this.
{
"a": "1",
"b": [
{
"d": 3
},
{
"d": 5
},
{
"d": 7
}
]
}

with data as (
select
your_json_col :: jsonb as obj,
jsonb_array_elements((your_json_col ->> 'b') :: jsonb) :: jsonb - 'c' as new_obj
from your_table)
select
obj || jsonb_build_object('b', jsonb_agg(new_obj))
from data
group by obj;

Related

DataWeave transform message two arrays with numbers

I would like compare two arrays (like input2) with numbers. And If the price is different about 5% increase, then I would like send email. I tried like this but it gave only the number that matches the same numbers. But I would like have only this price that it's increase 5% more.
%dw 2.0
output application/json
var input2 = [{
"T": "GIK",
"c": 10.02
},
{
"T": "EXTR",
"c": 4.43
},
{
"T": "TANH",
"c": 2.34
},
{
"T": "VSAT",
"c": 34.24
},
{
"T": "KIMpL",
"c": 25.9102
}]
---
payload.results.c reduce (item, acc = []) -> if (input2.c contains item) acc + item else acc
It appears from your script that you want the numbers (attribute c of input2 elements) that deviate a percentage from same attribute c from the payload. If you just need to compare the percentage from every number to every number in the other array this script does it. I used a function to calculate the percentage difference.
%dw 2.0
output application/json
import * from dw::core::Arrays
var maxPercentageDifference=5
fun percentageDifference(a,b)=abs(a-b)/((a+b)/2)*100
var input2 = [
{
"T": "GIK",
"c": 10.02
},
{
"T": "EXTR",
"c": 4.43
},
{
"T": "TANH",
"c": 2.34
},
{
"T": "VSAT",
"c": 34.24
},
{
"T": "KIMpL",
"c": 25.9102
}
]
---
payload.results.c
reduce (item, acc = []) -> if (input2.c some (percentageDifference(item, $) <= maxPercentageDifference)) acc + item else acc
Input:
{
"results": [
{
"T": "GIK",
"c": 10.05
},
{
"T": "EXTR",
"c": 4.41
},
{
"T": "TANH",
"c": 8
},
{
"T": "VSAT",
"c": 44
},
{
"T": "KIMpL",
"c": 25.9102
}
]
}
Output:
[
10.05,
4.41,
25.9102
]
However if you want to match the ids in attribute "T" before comparing the values, just change above script's body to:
payload.results
filter ((item, index) -> percentageDifference((input2 firstWith($.T == item.T)).c, item.c) <= maxPercentageDifference )
New Output:
[
{
"T": "GIK",
"c": 10.05
},
{
"T": "EXTR",
"c": 4.41
},
{
"T": "KIMpL",
"c": 25.9102
}
]

Want to parse string BLOB as JSON, modify few fields and parse it back to string BIGQUERY

So I have a column which contains JSONs as string BLOBs. For example,
{
"a": "a-1",
"b": "b-1",
"c":
{
"c-1": "c-1-1",
"c-2": "c-2-1"
},
"d":
[
{
"k": "v1"
},
{
"k": "v2"
},
{
"k": "v3"
}
]
}
Now my use case is to parse the key b, hash the value of key b, assign it back to the key b and store it back as a string in Bigquery.
I initially tried to do a lazy approach where I am only extracting the key b using the json_extract_scalar function in Bigquery and for other keys (like c and d - which I dont want to modify), I used json_extract function. Then I converted back to string after doing hashing the key b. Here is the query -
SELECT
TO_JSON_STRING(
STRUCT(
json_EXTRACT(COL_NAME, "$.a") AS a,
MD5(json_extract_scalar(_airbyte_data,"$.b")) AS b,
json_EXTRACT(COL_NAME,"$.c") AS c,
json_EXTRACT(COL_NAME,"$.d") AS d ) )
FROM
dataset.TABLE
But the issue with this query is the JSON objects are getting converted to string and double quotes getting escaped due to TO_JSON_STRING (I tried using CAST AS STRING on top of STRUCT but it isn't supported). For example, the output row for this query looks like this:
{
"a": "a-1",
"b": "b-1",
"c":
"{
\"c-1\": \"c-1-1\",
\"c-2\": \"c-2-1\"
}",
"d":
"[
{
\"k\": \"v1\"
},
{
\"k\": \"v2\"
},
{
\"k\": \"v3\"
}
]"
}
I can achieve the required output if I use JSON_EXTRACT and JSON_EXTRACT_SCALAR functions on every key (and on every nested keys) but this approach isn't scalable as I have close to 200 keys and many of them are nested 2-3 levels deep.
Can anyone suggest a better approach of achieving this? TIA
This should work
declare _json string default """{
"a": "a-1",
"b": "b-1",
"c":
{
"c-1": "c-1-1",
"c-2": "c-2-1"
},
"d":
[
{
"k": "v1"
},
{
"k": "v2"
},
{
"k": "v3"
}
]
}""";
SELECT regexp_replace(_json, r'"b": "(\w+)-(\w+)"',concat('"b":',TO_JSON_STRING( MD5(json_extract_scalar(_json,"$.b")))))
output
{
"a": "a-1",
"b":"sdENsgFsL4PBOyX8sXDN6w==",
"c":
{
"c-1": "c-1-1",
"c-2": "c-2-1"
},
"d":
[
{
"k": "v1"
},
{
"k": "v2"
},
{
"k": "v3"
}
]
}
If you need specific regex then please specify the example for b values.

Karate remove null value and the key from nested array list returned from DB [duplicate]

This question already has an answer here:
Comparing two JSON arrays in Karate DSL
(1 answer)
Closed 1 year ago.
for example, I get the below list when querying from the DB
[
{
"a":"123",
"b": "CAT"
}
{
"a": "456",
"b": null
}
{
"a":"789",
"b": "DOG"
}
{
"a":"134",
"b": null
}
]
I want to remove the key and value when the value is null
Expected
[
{
"a":"123",
"b": "CAT"
}
{
"a": "456"
}
{
"a":"789",
"b": "DOG"
}
{
"a":"134"
}
]
Please can someone help with this request, The reason I want to remove the null is the response which comes from the API ignores the null in the DB and looks like the expected, I have to match the response and the DB. Thanks in advance, Appreciate your time.
This is exactly what karate.filter() is for, please search for it (and read) the docs.
And in the latest version, this short-cut will also work:
* def list = [ { "a":"123", "b": "CAT" } { "a": "456", "b": null } { "a":"789", "b": "DOG" } { "a":"134", "b": null } ]
* def list = list.filter(x => x.b != null)
* print list

Dataweave to remove json elements from values after groupBy | Mule 3.9

I am trying to transform an xml based on groupBy in dataweave, however I also need to remove few json attributes from output.
Input json:
[ {
"m": {
"a": "a",
"b": "b"
},
"tag1": "A",
"tag2": "v1",
"tag3": "v1" }, {
"m": {
"a": "a",
"b": "b"
},
"tag1": "A",
"tag2": "v2",
"tag3": "v2" }, {
"m": {
"a": "a",
"b": "b"
},
"tag1": "C",
"tag2": "v3",
"tag3": "v3" } ]
Output json
**{
"A": [
{
"tag2": "v1",
"tag3": "v1"
},
{
"tag2": "v2",
"tag3": "v2"
}
],
"C": {
"tag2": "v3",
"tag3": "v3"
}
}**
I have tried following transformation (Mule 3.9) however the could not remove the extra attributes in json.
payload groupBy (item) -> item.tag1
Appreciate any suggestion on this and possibly explain how this can be achieved.
The way to iterate over an object is using mapObject and then you can filter the objects to remove the elements that are not wanted
{a: [1,2,3], b: [2,3]} mapObject ((value,key) ->
{
(key): value filter ((value, index) -> value > 2)
}
)
This will output
{
"a": [
3
],
"b": [
3
]
}

How do I write a SQL query for a shown azure cosmos db documents?

I have following documents in azure cosmos db collection.
// Document 1
{
"c": {
"firstName": "Robert"
}
"elements" : [
{
"a": "x2",
"b": {
"name": "yadda2",
"id": 1
}
}
]
}
// Document 2
{
"c": {
"firstName": "Steve"
}
"elements" : [
{
"a": "x5",
"b": {
"name": "yadda2",
"id": 4
}
},
{
"a": "x3",
"b": {
"name": "yadda8",
"id": 5
}
},
]
}
// Document 3
{
"c": {
"firstName": "Johnson"
}
"elements" : [
{
"a": "x4",
"b": {
"name": "yadda28",
"id": 25
}
},
{
"a": "x5",
"b": {
"name": "yadda30",
"id": 37
}
},
]
}
I need to write a query that returns all documents which have "b" object whose name is "yadda2" (i.e. /elements/*/b/name=yadda2). In other words, this query should return document 1 and 2 but NOT 3.
I tried following but it did not work:
SELECT * FROM x where ARRAY_CONTAINS(x.elements, {b: { name: "yadda2"}})
What am I doing wrong?
Just modify your sql to :
SELECT * FROM x where ARRAY_CONTAINS(x.elements, {b: { name: "yadda2"}},true)
Result:
Based on the official doc , the boolean expression could specify if the match is full or partial.
Hope it helps you.