Using PostgreSQL JSON function to obtain an array object from a JSON stored key - sql

I have a table on AWS RDS PostgreSQL that stores JSON objects. For instance I have this registry:
{
"id": "87b05c62-4153-4341-9b58-e86bade25ffd",
"title": "Just Ok",
"rating": 2,
"gallery": [
{
"id": "1cb158af-0983-4bac-9e4f-0274b3836cdd",
"typeCode": "PHOTO"
},
{
"id": "aae64f19-22a8-4da7-b40a-fbbd8b2ef30b",
"typeCode": "PHOTO"
}
],
"reviewer": {
"memberId": "2acf2ea7-7a37-42d8-a019-3d9467cbdcd1",
},
"timestamp": {
"createdAt": "2011-03-30T09:52:36.000Z",
"updatedAt": "2011-03-30T09:52:36.000Z"
},
"isUserVerified": true,
}
And I would like to create a query for obtaining one of the gallery objects.
I have tried this but get both objects in the array:
SELECT jsonb_path_query(data->'gallery', '$[*]') AS content
FROM public.reviews
WHERE jsonb_path_query_first(data->'gallery', '$.id') ? '1cb158af-0983-4bac-9e4f-0274b3836cdd'
With this other query I get the first object:
SELECT jsonb_path_query_first(data->'gallery', '$[*]') AS content
FROM public.reviews
WHERE jsonb_path_query_first(data->'gallery', '$.id') ? '1cb158af-0983-4bac-9e4f-0274b3836cdd'
But filtering by the second array object id, I get no result:
SELECT jsonb_path_query_first(data->'gallery', '$[*]') AS content
FROM public.reviews
WHERE jsonb_path_query_first(data->'gallery', '$.id') ? 'aae64f19-22a8-4da7-b40a-fbbd8b2ef30b'
I have read the official documentation and tried other functions like jsonb_path_exists or jsonb_path_match on the where condition but was not able to make the query work.
Any help would be greatly appreciated. Thanks in advance.

I managed to get the query working as needed. Here is my proposal:
SELECT gallery
FROM public.reviews, jsonb_path_query(data->'gallery', '$[*]') as gallery
WHERE data->>'id' = '87b05c62-4153-4341-9b58-e86bade25ffd' and gallery->>'id' = 'aae64f19-22a8-4da7-b40a-fbbd8b2ef30b'
Hope it helps others.

Related

Query for entire JSON document in nested JSON schema

Background:
I wish to locate the entire JSON document that has a condition where "state" = "new" and where length(Features.id) > 4
{
"id": "123"
"feedback": {
"Features": [
{
"state": "new"
"id": "12345"
}
]
}
}
This is what I have tried to do:
Since this is a nested document. My query looks like this:
A stackoverflow member has helped me to access the nested contents within the query, but is there a way to obtain the full document
I have used:
SELECT VALUE t.id FROM t IN f.feedback.Features where t.state = 'new' and length(t.id)>4
This will give me the ids.
My desire is to have access to the full document with this condition?
{
"id": "123"
"feedback": {
"Features": [
{
"state": "new"
"id": "12345"
}
]
}
}
Any help is appreciated
Try this
SELECT *
FROM f
WHERE
f.feedback.Features[0].state = 'new'
AND length(f.feedback.Features[0].id)>4
Here is the SELECT spec for CosmosDB for more details
https://learn.microsoft.com/en-us/azure/cosmos-db/sql-query-select
Also, check out "working with JSON" in CosmosDB notes
https://learn.microsoft.com/en-us/azure/cosmos-db/sql-query-working-with-json
If the Features array has more than 1 value, you can use EXISTS clause to search within them. See specs of EXISTS here with examples:
https://learn.microsoft.com/en-us/azure/cosmos-db/sql-query-subquery#exists-expression

How to extract the field from JSON object with QueryRecord

I have been struggling with this problem for a long time. I need to create a new JSON flowfile using QueryRecord by taking an array (field ref) from input JSON field refs and skip the object field as shown in example below:
Input JSON flowfile
{
"name": "name1",
"desc": "full1",
"refs": {
"ref": [
{
"source": "source1",
"url": "url1"
},
{
"source": "source2",
"url": "url2"
}
]
}
}
QueryRecord configuration
JSONTreeReader setup as Infer Schema and JSONRecordSetWriter
select name, description, (array[rpath(refs, '//ref[*]')]) as sources from flowfile
Output JSON (need)
{
"name": "name1",
"desc": "full1",
"references": [
{
"source": "source1",
"url": "url1"
},
{
"source": "source2",
"url": "url2"
}
]
}
But got error:
QueryRecord Failed to write MapRecord[{references=[Ljava.lang.Object;#27fd935f, description=full1, name=name1}] with schema ["name" : "STRING", "description" : "STRING", "references" : "ARRAY[STRING]"] as a JSON Object due to java.lang.ClassCastException: null
Try the following approach, in your case it shoud work:
1) Read your JSON field fully (I imitated it with GenerateFlowFile processor with your example)
2) Add EvaluateJsonPath processor which will put 2 header fileds (name, desc) into the attributes:
3) Add SplitJson processor which will split your JSON byt refs/ref/ groups (split by "$.refs.ref"):
4) Add ReplaceText processor which will add you header fields (name, desc) to the split lines (replace "[{]" value with "{"name":"${json.name}","desc":"${json.desc}","):
5) It`s done:
Full process in my demo case:
Hope this helps.
Solution!: use JoltTransformJSON to transform JSON by Jolt specification. About this specification.

How to check if json array already contains a certain key?

Let's say I have this json in my jsonb column
{
"fields": [
{
"name": "firstName",
},
{
"name": "lastName",
},
...
}
How can I know if the "firstName" already exist?
I've tried this so far
SELECT field->>'fields'
from person where (field->'name')::jsonb ? 'firstName';
Use the containment operator #>:
select field->>'fields'
from person
where field->'fields' #> '[{"name": "firstName"}]'
you can use json_array_elements to generate fields elements so you can filter based on 'name'.
SELECT field->>'fields', obj.*
from person, jsonb_array_elements_text(field->'fields') obj
where obj = '{"name": "firstName"}'
see dbfiddle

How to Query Cosmos DB graph by use of SQL CONTAINS

I have a Cosmo DB graph where I would like to access the 'name' field in an expression using the string matching CONTAINS in Cosmos DB. CONTAINS works at 1 level as in matching CONATINS
SELECT s.label, s.name FROM s WHERE CONTAINS(LOWER(s.name._value), "cara") AND s.label = "site"
I also tried with a UDF function
SELECT s.label, s.name FROM s WHERE(s.label = 'site' AND udf.strContains(s.name._value, '/cara/i'))
I don't get any hits or syntax errors from Cosmos DB even that should be at least one record in this example. Does anyone have a hint? Thanks in advance
[
{
"label": "site",
"name": [
{
"_value": "0315817 Caracol",
"id": "2e2f000d-2e0a-435a-b472-75d257236558"
}
]
},
{
"label": "site",
"name": [
{
"_value": "0315861 New Times",
"id": "48497172-1734-43d0-9866-51faf9f603ed"
}
]
}
]
I noticed that the name property is an array not an object.So, you need to use join in sql.
SELECT s.label, s.name , name._value FROM s
join name in s.name
where CONTAINS(LOWER(name._value), "cara") AND s.label = "site"
Output:
Hope it helps you.

Get value from array in JSON in SQL Server

Let's say we have this json in our database table. I want to select value from tags. I already know how to get an array from this data but I don't know how to access array members. The question would be how do I get the first value from the array? Is there a function for this task?
{
"info": {
"type": 1,
"address": {
"town": "Bristol",
"county": "Avon",
"country": "England"
},
"tags": ["Sport", "Water polo"]
},
"type": "Basic"
}
Query I already have:
SELECT JSON_QUERY(MyTable.Data, '$.info.tags')
FROM MyTable
This returns me:
["Sport", "Water polo"]
How do I get
Sport
JSON_QUERY returns an object or array. You need JSON_VALUE to return a scalar value, eg :
SELECT JSON_VALUE(Data, '$.info.tags[0]')
from MyTable
Check the section Compare JSON_VALUE and JSON_QUERY in the docs for more examples