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
Related
I have JSONB data in a Postgres column like this:
{
"Id": "5c6d3210-1def-489b-badd-2bcc4a1cda28",
"Name": "Jane Doe",
"Tags": [
{
"Key": "Project",
"Value": "1004345"
}
]
}
How can I query data where Name contains "Jane" or "Tags.Key" contains "4345"?
I tried this but this only matches the exact "Key" value:
select * from documents where data->'Tags' #> '[{ "Value":"1004345"}]';
You can use a JSON path operator using like_regex
select *
from documents
where data ## '$.Tags[*].Value like_regex "4345"'
you can do this way
select *
from documents
where 'Tags' ->> 'Value' = '1004345';
Column states has type jsonb
Example:
[{
"dt": "2020-12-18T16:19:45.378+00:00",
"id": "confirmed"
},
{
"dt": "2020-12-16T12:11:45.210+00:00",
"id": "delivery"
},
{
"dt": "2020-12-16T11:25:08.444+00:00",
"id": "new"
}
]
If I want to find is first item's in array id = confirmed
I use this
select id, states from my_table where states->0->>'id' = 'confirmed'
Nice. It's work fine.
But... I need is check is exist id = confirmed in ANY array's items.
Is it possible?
You can use the contains operator #>
select id, states
from my_table
where states #> '[{"id": "confirmed"}]'
SELECT * FROM some_table;
I can query to get the following results:
{
"sku0": {
"Id": "18418",
"Desc": "yes"
},
"sku1": {
"Id": "17636",
"Desc": "no"
},
"sku2": {
"Id": "206714",
"Desc": "yes"
},
"brand": "abc",
"displayName": "something"
}
First, the number of skus is not fixed. It may be sku0, sku1, sku2, sku3, sku4 ... but they all start with sku.
Then, I want to query Id with 17636 and determine whether its value of Desc is yes or no. After reading the PostgreSQL JSON Functions and Operators documentation, Depressing I didn't find a good way.
I can convert the result into a Python dictionary, and then use python's method can easily achieve my requirements.
If the requirements can also be achieved with postgresql statements, which method is more recommended than the Python dictionary?
I am not sure I completely understand what the result is you want. But if you want to filter on the Id, you need to unnest all the elements inside the JSON column:
select d.v ->> 'Desc' as description
from the_table t
cross join jsonb_each(t.data) as d(k,v)
where d.v ->> 'Id' = '17636'
You could use the new jsonpath notation of PostgreSQL v12:
SELECT data ## '$.* ? (#.Id == "17636").Desc == "yes"'
FROM some_table;
That will start with the root of data ($), find any attribute in it (*), filter only those attributes that contain an Id with value "17636", get their Desc attribute and return TRUE only if that attribute is "yes".
Nice, isn't it?
This will probably give you what you need.
select value->>'Desc' from jsonb_each('{
"sku0": {
"Id": "18418",
"Desc": "yes"
},
"sku1": {
"Id": "17636",
"Desc": "no"
},
"sku2": {
"Id": "206714",
"Desc": "yes"
},
"brand": "abc",
"displayName": "something"
}'::jsonb)
where key like 'sku%'
and value->>'Id'='17636'
Best regards,
Bjarni
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
My JSON data looks like this:
[{
"id": 1,
"payload": {
"location": "NY",
"details": [{
"name": "cafe",
"cuisine": "mexican"
},
{
"name": "foody",
"cuisine": "italian"
}
]
}
}, {
"id": 2,
"payload": {
"location": "NY",
"details": [{
"name": "mbar",
"cuisine": "mexican"
},
{
"name": "fdy",
"cuisine": "italian"
}
]
}
}]
given a text "foo" I want to return all the tuples that have this substring. But I cannot figure out how to write the query for the same.
I followed this related answer but cannot figure out how to do LIKE.
This is what I have working right now:
SELECT r.res->>'name' AS feature_name, d.details::text
FROM restaurants r
, LATERAL (SELECT ARRAY (
SELECT * FROM json_populate_recordset(null::foo, r.res#>'{payload,
details}')
)
) AS d(details)
WHERE d.details #> '{cafe}';
Instead of passing the whole text of cafe I want to pass ca and get the results that match that text.
Your solution can be simplified some more:
SELECT r.res->>'name' AS feature_name, d.name AS detail_name
FROM restaurants r
, jsonb_populate_recordset(null::foo, r.res #> '{payload, details}') d
WHERE d.name LIKE '%oh%';
Or simpler, yet, with jsonb_array_elements() since you don't actually need the row type (foo) at all in this example:
SELECT r.res->>'name' AS feature_name, d->>'name' AS detail_name
FROM restaurants r
, jsonb_array_elements(r.res #> '{payload, details}') d
WHERE d->>'name' LIKE '%oh%';
db<>fiddle here
But that's not what you asked exactly:
I want to return all the tuples that have this substring.
You are returning all JSON array elements (0-n per base table row), where one particular key ('{payload,details,*,name}') matches (case-sensitively).
And your original question had a nested JSON array on top of this. You removed the outer array for this solution - I did the same.
Depending on your actual requirements the new text search capability of Postgres 10 might be useful.
I ended up doing this(inspired by this answer - jsonb query with nested objects in an array)
SELECT r.res->>'name' AS feature_name, d.details::text
FROM restaurants r
, LATERAL (
SELECT * FROM json_populate_recordset(null::foo, r.res#>'{payload, details}')
) AS d(details)
WHERE d.details LIKE '%oh%';
Fiddle here - http://sqlfiddle.com/#!15/f2027/5