get first element from jsonb list of strings postgres - postgresql

I have a List which is stored in my table as a jsonb and need a native query to get the first element from this jsonb column
Tried using jsonb_array_elements_text but couldn't get it to work.
select col from tbl;
returns:
["abc", "def", "etc"]
I need a query which can just return me abc

You can use the operator that picks the n-th element of an array:
select col ->> 0 as first_element
from tbl;
Note that unlike Postgres native arrays, the first element in a JSON array has the index 0

Related

Query to search over array elements inside jsonb PSQL

I have a JSON node on which I have to write a PSQL query, My table schema name(String),tagValues(jsonb). Example tagValue data is given below
Name_TagsTable
uid | name(String)| tagValues(jsonb)
-----+-------------------+-----------------------------
1 | myName | { "tags": ["xyz","pqr","xyp"]}
I need a query that returns all rows for a search "pq" made on the tagValues of the table
select * from Name_TagsTable where tagValues->tags contains %pq%
You can use LIKE operator along with casting JSONB value to a string type such as
SELECT *
FROM Name_TagsTable
WHERE (tagValues->'tags')::TEXT LIKE '%pq%'
You need to unnest the elements, then you can use it in a WHERE condition that applies a LIKE condition.
select nt.*
from name_tagstable nt
where exists (select *
from jsonb_array_elements_text(tagvalue -> 'tags') as a(tag)
where a.tag like '%pg%');

Casting an array of strings to an array of integers

How can I cast an array of string into an array of integers?
Below is my array
["6", "5"]
I want convert into int array
[6, 5]
demo:db<>fiddle
SELECT
array_agg(elems::int)
FROM unnest(ARRAY['5', '6']) as elems
Expand the array into one record per element
Reaggregate cast integer values
To ensure the original order, you need to add WITH ORDINALITY, which adds an index to the original array:
SELECT
array_agg(elems.value::int ORDER BY elems.index)
FROM unnest(ARRAY['5', '6']) WITH ORDINALITY as elems(value, index)
If you have a JSON array instead, the algorithm is the same, only the used functions have different names:
SELECT
json_agg(elems.value::int ORDER BY elems.index)
FROM json_array_elements_text('["5", "6"]'::json) WITH ORDINALITY as elems(value, index)
EDIT: According to comment:
this is my query. SELECT data->>'pid' FROM user_data where
data->>'pid' is not null How can I update pid to array of integers ?
demo:db<>fiddle
You have to expand and reaggregate nonetheless:
SELECT
json_agg(elems::int) -- 2
FROM user_data,
json_array_elements_text(data -> 'pid') as elems -- 1
WHERE data->>'pid' IS NOT NULL
GROUP BY id
You can’t “cast”, but you can get something very close to a cast:
array(select unnest(myArray)::int)
As a testable query:
select array(select unnest(array['5', '6'])::int)
See live demo.
When applying to a column of a selected table:
select
array(select unnest(myArrayCol)::int)
from myTable
See live demo.
This syntax preserves order.

Remove Key Value pair from jsonb nested array in postgresql

I have jsonb data as
{
"a":[
{"b":1,"c":2,"d":3},
{"b":4,"c":5,"d":6}
],
"g":[
{"b":1,"c":2,"d":3},
{"b":4,"c":5,"d":6}
]
}
I want to remove c key from nested array in both "a" and "g" keys. Is there a single query to perform this?
step-by-step demo: db<>fiddle
SELECT
jsonb_object_agg(key, a) -- 5
FROM (
SELECT
mydata,
key,
jsonb_agg(a_elems.value - 'c') as a -- 3/4
FROM
mytable,
jsonb_each(mydata) elems, -- 1
jsonb_array_elements(elems.value) AS a_elems -- 2
GROUP BY mydata, key -- 4
) s
GROUP BY mydata -- 5
Expand the JSON elements into one row each. This generates two columns: One for the key and one for the value (the JSON array)
Expand the JSON array into one row each (which separates the aggregated JSON object from which you want to remove the c element)
You can use the - operator to remove the element.
To reaggregate the original JSON object, you need to group it backwards. jsonb_agg() reaggregates the arrays
Finally you need to rebuild the original JSON object with jsonb_object_agg() using the previously generated key column and the new array column.

Build jsonb array from jsonb field

I have column options with type jsonb , in format {"names": ["name1", "name2"]} which was created with
UPDATE table1 t1 SET options = (SELECT jsonb_build_object('names', names) FROM table2 t2 WHERE t2.id= t1.id)
and where names have type jsonb array.
SELECT jsonb_typeof(names) FROM table2 give array
Now I want to extract value of names as jsonb array. But query
SELECT jsonb_build_array(options->>'names') FROM table
gave me ["[\"name1\", \"name2\"]"], while I expect ["name1", "name2"]
How can I get value in right format?
The ->> operator will return the value of the field (in your case, a JSON array) as a properly escaped text. What you are looking for is the -> operator instead.
However, note that using the jsonb_build_array on that will return an array containing your original array, which is probably not what you want either; simply using options->'names' should get you what you want.
Actually, you don't need to use jsonb_build_array() function.
Use select options -> 'names' from table; This will fix your issue.
jsonb_build_array() is for generating the array from jsonb object. You are following wrong way. That's why you are getting string like this ["[\"name1\", \"name2\"]"].
Try to execute this sample SQL script:
select j->'names'
from (
select '{"names": ["name1", "name2"]}'::JSONB as j
) as a;

Querying jsonb column containing a json array with a single element

I want to be able to use the same query syntax to return both rows
Given a jsonb column, named 'tags' in a table called 'qux' with sample data in row 1:
{
"foo": ["1","2"]
}
and row 2:
{
"foo": ["3"]
}
and the pre-requisite index created on the column 'tags':
CREATE INDEX tag_idx ON tags USING GIN (tags);
When I run the following query:
SELECT count(*) FROM "qux" WHERE tags #> '{"foo": ["1"]}'
I expect to get a row back, which is correct.
If I run:
SELECT count(*) FROM "qux" WHERE tags #> '{"foo": ["3"]}'
I do not get any rows back, which feels unexpected. I can get the row back if I remove the square brackets on the second example, however that syntax breaks the first example.
Is this a known bug, or a problem with indexing? The version of postgres is 9.5