get array matches with json - sql

I have field in database with type json:
[{"id": "1"}, {"id": "2"}, {"id": "3"}]
and I need get matches in json with array ["1", "2"] for at least one element.

Something like this:
select t.*
from the_table t
where exists (select *
from jsonb_array_elements(t.the_column) as x(item)
join jsonb_array_elements_text('["1", "2"]') as e(id)
on x.item ->> 'id' = e.id);
Online example

Related

ILIKE query inside arrays of objects in jsonb column

I have a jsonb data column made up of various objects. Here is an example.
{"LicensePlates": {"Type": "LicensePlateList", "Value": ["XXXXX"]}, "SubscriptionInfo": {"Type": "SubscriptionInfoList", "Value": [{"id": "1", "lastname": "rossi", "firstname": "paola"}, {"id": "2", "lastname": "Scicolone", "firstname": "Paolo"}]}}
Now I'm searching a specific info in SubscriptionInfo key like this:
SELECT * FROM column WHERE (data -> 'SubscriptionInfo') -> 'Value' #> '[{"firstname": "Paolo"}]';
It works fine, but I would also like to search for "partial" information, eg. searching for the string "pa" (using ILIKE or anything else similar) should return the entire record. it's possible?
You have two options (demo)
convert data to lower case
select *
from
test
where
lower(data -> 'SubscriptionInfo' ->> 'Value')::jsonb #> lower('[{"firstname": "paolo"}]')::jsonb;
Use cross join and extract JSON then use ilike
select distinct on (t.id) t.*
from
test t
cross join jsonb_array_elements(data -> 'SubscriptionInfo' -> 'Value') ej
where
value ->> 'firstname' ilike '%paolo%';
If you are using Postgres 13 or later, you can use a SQL/JSON path expression:
select t.*
from the_table t
where t.data ## '$.SubscriptionInfo.Value[*].firstname like_regex "paolo" flag "i"'

Search by json key in jsonb column PostgreSQL

I have a table with following structure (simplified):
Sometable:
id
data
1
{"data": [{"type": {"code": "S"}}, {"type": {"code": "aB"}}]}
2
{"data": [{"type": {"code": "B"}}]}
'Data' is jsonb type, json structure is always the same. I need to find all records where 'code equals certain value, for example 'B'.
I've tried:
select * from sometable t
where 'B' in (jsonb_array_elements((t.data->'data'))#>>'{type, code}');
But that gives me an error:
set-returning functions are not allowed in WHERE.
Basically, anything I've tried in 'where' with 'jsonb_array_elements' gives that error. Is there any other way to find records by value of the 'code' key?
You can use the #> operator
select *
from sometable t
where (t.data -> 'data') #> '[{"type": {"code": "B"}}]'
or
select *
from sometable t
where t.data #> '{"data": [{"type": {"code": "B"}}]}'
Online example

Query all objects within json array

I'm looking to do a query on a column in my database but the column is of type jsonb. This is an example of the structure:
select json_column->>'left' from schema.table;
[{"id": 123, "name": "Joe"},
{"id": 456, "name": "Jane"},
{"id": 789, "name": "John"},
{"id": 159, "name": "Jess"}]
Essentially I'm just trying to return all the name fields from this but I can't figure it out.
I have tried
select json_column->'left'->>'name' from schema.table
But this returns a blank value just.
I have also tried:
select elem->>'name'
from schema.table m,
jsonb_array_elements(json_column->'left') elem;
But that gives me:
ERROR: cannot extract elements from an object
This seems to work when I have a where clause inserted, for example:
select elem->>'name'
from schema.table m,
jsonb_array_elements(json_column->'left') elem
where m.id = 1;

Select from JSON Array postgresql JSON column

I have the following JSON stored in a PostgreSQL JSON column
{
"status": "Success",
"message": "",
"data": {
"serverIp": "XXXX",
"ruleId": 32321,
"results": [
{
"versionId": 555555,
"PriceID": "8abf35ec-3e0e-466b-a4e5-2af568e90eec",
"price": 550,
"Convert": 0.8922953080331764,
"Cost": 10
}
]
}
}
I would like to search for a specific priceID across the entire JSON column (name info) and select the entire results element by the PriceID.
How do i do that in postgresql JSON?
One option uses exists and json(b)_array_elements(). Assuming that your table is called mytable and that the jsonb column is mycol, this would look like:
select t.*
from mytable t
where exists (
select 1
from jsonb_array_elements(t.mycol -> 'data' -> 'results') x(elt)
where x.elt ->> 'PriceID' = '8abf35ec-3e0e-466b-a4e5-2af568e90eec'
)
In the subquery, jsonb_array_elements() unnest the json array located at the given path. Then, the where clause ensures that at least one elment in the array has the given PriceID.
If your data is of json datatype rather than jsonb, you need to use json_array_elements() instead of jsonb_array_elements().
If you want to display some information coming from the matching array element, then it is different. You can use a lateral join instead of exists. Keep in mind, though, that this will duplicate the rows if more than one array element matches:
select t.*, x.elt ->> 'price' price
from mytable t
cross join lateral jsonb_array_elements(t.mycol -> 'data' -> 'results') x(elt)
where x.elt ->> 'PriceID' = '8abf35ec-3e0e-466b-a4e5-2af568e90eec'

JSONB sort aggregation

I found this query that suits my needs thanks to this answer here in order to sort fields of data in a JSON document.
(Fake, generated random data)
SELECT jsonb_agg(elem)
FROM (
SELECT *
FROM jsonb_array_elements('[{
"id": "1",
"first_name": "Maximo",
"last_name": "Sambiedge",
"email": "msambiedge0#economist.com",
"gender": "Male",
"ip_address": "242.145.232.65"
}, {
"id": "2",
"first_name": "Maria",
"last_name": "Selland",
"email": "aselland1#sitemeter.com",
"gender": "Female",
"ip_address": "184.174.58.32"
}]') a(elem)
ORDER BY (elem->>'email') -- order by integer value of "ts"
) sub;
As we can see, this works with hardcoded data which doesn't quite fit my needs. I can't seem to figure out how to replace the JSON data with the jsonb column in my table.
My attempt below yields 'data is not defined'
SELECT jsonb_agg(elem), (SELECT data FROM file_metadata)
FROM (
SELECT *
FROM jsonb_array_elements(data) a(elem)
ORDER BY (elem->>'email')
) sub;
My suspicions are that a subquery is needed inside the FROM clause?
Here is a SQLFiddle of my issue to help describe the table and how the structure is defined: http://sqlfiddle.com/#!17/41102/92
You are almost there. You just need to bring in the original table, like so:
SELECT jsonb_agg(elem)
FROM (
SELECT elem
FROM file_metadata, jsonb_array_elements(data) a(elem)
ORDER BY (elem->>'email')
) sub;
Updated DB Fiddle