How to access json array elements (keys) , values in json nested dictionary type using postgresql? - sql

I have a nested structure json .
How to extract the specific elements(keys) and values?
How to access " sky: selling":"1"
Or "U1":"0000" ?
I tried json_object_keys and json_array_elements for extracting the array .
But I don't know exactly how to do this query.
Example code:
Table- record and column name : report
{
"PIname": {
"n1": "x1",
"n2": "x2",
"params": {
"S1": {
"code1": "y1",
"Code2": "y2",
},
"id": "2d",
"Dest": {
"Code3": "mi"
}
},
"PIDataArea": {
"m1": null,
"PInven": {
"head": {
"Code4": "Increase",
"line": "2020-01"
},
"PILine": [
{
"u1": "0000",
"u2": "0",
"u3": "1",
"modes": {
"#cID": "Sng",
"#txt": "12.21"
} },
{
"Qualify": ".0001",
"QOrder": "1",
"UPriceAmt": {
"#cID": "sng",
"#txt": "13" },
"sky:Qa": ".000",
"sky:Partcode": {
"#c1ID": "a"
},
"sky:SCode": "Ni",
"sky:PItem": {
"sky:ID": "h"
},
"sky:Forest": {
"sky:q1": [
{
"sky:selling": "1"
}
{
"sky:selling": "0"
}
]
} } }} }}
I tried lot ,one example query here like,
Select * from record r
Where exists( select report->'sky: selling' from json_each(r.report) b where b.value->>'sky:selling' Ilike '0');

You can use the json_path_query or jsonb_path_query function. Example to extract the element with key = "sky:selling" :
json_path_query(r.report, $.** ? (#.key == 'sky:selling'))

Related

Query item in nested array

Customer appointments with top level locationId sample data set:
[
{
"locationId": 9999,
"customerAppointments": [
{
"customerId": "1",
"appointments": [
{
"appointmentId": "cbbce566-da59-42c2-8845-53976ba63d56",
"locationName": "Sullivan St"
},
{
"appointmentId": "5f09e2af-ddae-47aa-9f7c-fd1001a9c5e6",
"locationName": "Oak St"
}
]
},
{
"customerId": "2",
"appointments": [
{
"appointmentId": "964a3c1c-ccec-4082-99e2-65795352ba79",
"locationName": "Kellet St"
}
]
},
{
"customerId": "3",
"appointments": []
}
]
},
{
...
},
{
...
}
]
I need to pull out appointment by locationId and customerId and only get the appointment for that customerId e.g
Sample response:
[
{
"appointmentId": "964a3c1c-ccec-4082-99e2-65795352ba79",
"locationName": "Kellet St"
}
]
Tried below query, but it just returns all records for all customers ids (which is kind of expected):
db.getCollection("appointments").find(
{
"locationId" : NumberInt(9999),
"customerAppointments" : {
"$elemMatch" : {
"customerId" : "2"
}
}
}
);
But how can I get just the appointment record for a specific customerId?
When asking this question I was unaware of the older version of MongoDB driver (< v5) so we cannot use the $getField operator.
However, this query seems to work well:
db.getCollection("appointments").aggregate([
{
$match: {
"locationId": NumberInt(9999)
}
},
{
$unwind: "$customerAppointments"
},
{
$match: {
"customerAppointments.customerId": "2"
}
},
{
$project: {
appointments: "$customerAppointments.appointments"
}
}
]);
Yields:
{
"_id" : ObjectId("63eebe95c7a0da54804c1db2"),
"appointments" : [
{
"appointmentId" : "964a3c1c-ccec-4082-99e2-65795352ba79",
"locationName" : "Kellet St"
}
]
}

Postgres 12.9 - Getting the value of a json array on matching key

I have a column in my database that stores a json string listing the weapons used in each game activity, what I need to be able to do is return the 'values'->'uniqueWeaponKills'->'basic'->'value' when the 'referenceId' key = 1994645182, and 0 if the key,value pair is not in the column.
Example 'weapons' column data
{
"weapons": [
{
"values": {
"uniqueWeaponKills": {
"basic": {
"value": 14,
"displayValue": "14"
}
},
"uniqueWeaponPrecisionKills": {
"basic": {
"value": 0,
"displayValue": "0"
}
},
"uniqueWeaponKillsPrecisionKills": {
"basic": {
"value": 0,
"displayValue": "0%"
}
}
},
"referenceId": 1994645182
},
{
"values": {
"uniqueWeaponKills": {
"basic": {
"value": 2,
"displayValue": "2"
}
},
"uniqueWeaponPrecisionKills": {
"basic": {
"value": 1,
"displayValue": "1"
}
},
"uniqueWeaponKillsPrecisionKills": {
"basic": {
"value": 0.5,
"displayValue": "50%"
}
}
},
"referenceId": 1853180924
}
]
}
Edit 1:
Using the suggestion from Kendle I got to the following query, I haven't seen a way to dynamically look in each of the array elements instead of having to specify the one to look at.
Query
select weapons::json->'weapons'->1->'values'->'uniqueWeaponKills'->'basic'->>'value' as "uniqueWeaponKills",
weapons::json->'weapons'->1->'referenceId' as "weaponId"
from activities
where (weapons::json->'weapons'->1->>'referenceId')::BIGINT = 1687353095;
You could try
SELECT
weapons::json->'values'->> 'uniqueWeaponKills'->>'basic' ->>'value'
FROM table_name
WHERE
weapons::json->'referenceId' = 1994645182;
See also How to parse JSON in postgresql
I think I found the solution I am looking for using json_array_elements()
SELECT obj->'values'->'uniqueWeaponKills'->'basic'->>'value' as "uniqueWeaponKills"
FROM activities a, json_array_elements(a.weapons#>'{weapons}') obj
WHERE (obj->>'referenceId')::BIGINT = 1687353095;

how to select value if key is uuid in mongodb

the mongodb data like this:
{
"_id": "123dsadasfa454sdsaw",
"hashmap": {
"uuid-12sadsadw5": {
"name": "bob"
},
"uuid-12sadsadwew5": {
"name": "alice"
}
},
"age": 10
}
"hashmap" like java HashMap, the key is uuid like "uuid-12sadsadwew5" and the value is object.
I want to get the data which the name in "hashmap" value is not null. And I use sql :
db.tabl1.find({"hashmap.values.name":{$ne:null}})
but cannot get the right result
You can use this aggregation query:
First use $objectToArray to create an array with values k and v. As we don't know the key (k) we can search by value (v).
Then $unwind array
And $match values where name is not null.
And then regroup and recreate the object using $arrayToObject.
db.collection.aggregate([
{
"$set": {
"hashmap": {
"$objectToArray": "$hashmap"
}
}
},
{
"$unwind": "$hashmap"
},
{
"$match": {
"hashmap.v.name": {
"$ne": null
}
}
},
{
"$group": {
"_id": "$_id",
"hashmap": {
"$push": "$hashmap"
}
}
},
{
"$set": {
"hashmap": {
"$arrayToObject": "$hashmap"
}
}
}
])
Example here

Postgres/JSON Updating nested array elements

Given the input JSON from the 'table' under a column named '_value'. I would like to replace the field "sc" as text from object to value of name under sc.
The json before updating looks like this.
{
"iProps": [
{
"value": {
"rules": [
{
"ao": {
"sc": {
"web_link": "abc.com",
"name": "name"
}
}
},
{
"ao": {
"sc": ""
}
}
]
}
}
]
}
The json after updating should look like this.
{
"iProps": [
{
"value": {
"rules": [
{
"ao": {
"sc": "name"
}
},
{
"ao": {
"sc": ""
}
}
]
}
}
]
}
I tried the below query to get to 'rules' array but having difficulty to proceed further in parsing and updating.
WITH values AS (
SELECT iprop -> 'value' -> 'rules' AS value FROM
table t,jsonb_array_elements(t._value->'iProps') AS
iprop )
SELECT *
from values, jsonb_array_elements(values.ao)
throws following error
ERROR: column values.ao does not exist
LINE 26: from values, jsonb_array_elements(values.ao)
^
SQL state: 42703
Character: 1396
You can try below mentioned query considering your structure is constant and the data type of your column is JSONB.
with cte as (
select
vals2->'ao'->'sc'->'name' as namevalue,
('{iProps,'||index1-1||',value,rules,'||index2-1||',ao,sc}')::text[] as json_path
from
table_,
jsonb_array_elements(value_->'iProps')
with ordinality arr1(vals1,index1),
jsonb_array_elements(vals1->'value'->'rules')
with ordinality arr2(vals2,index2)
)
update table_
set value_ = jsonb_set(value_,cte.json_path,cte.namevalue,false)
from cte
WHERE cte.namevalue IS NOT NULL
DEMO

How to only include a key if the value meets a certain criteria

I have this piece of Dataweave code
list_of_orders: {
order: payload map ((payload01 , indexOfPayload01) -> {
order_dtl:
"" when payload01[30] == "S"
otherwise
"" when payload01[30] == "C"
otherwise
[{
data: some_data
}],
order_hdr: {
data: some_data
}
})
}
This code will output the following data
"list_of_orders": {
"order": [
{
"order_dtl": [
{
"data": "some_data"
}
],
"order_hdr": {
"data": "some_data"
}
}
]
}
But it will only do this if payload01[30] != "S" or "C"
If payload01[30] is equal to "S" or "C" then it does this
"list_of_orders": {
"order": [
{
"order_dtl": "",
"order_hdr": {
"data": "some_data"
}
}
]
}
The reason I have done this is because I have been asked to only include the DETAIL line if the order_type is not "C" or "S".
The problem is that the actual key - order_dtl - is still present and I don't want anything there at all.
How do I make a KEY conditional?
Any help appreciated
Thanks
What you are looking is called conditional elements
list_of_orders: {
order: payload map ((payload01 , indexOfPayload01) -> {
(order_dtl:
[{
data: some_data
}]) when((payload01[30] != "S") and (payload01[30] != "C")),
order_hdr: {
data: some_data
}
})
}