How to use LIKE on elements of a JSONB array? - arrays

I need to search with LIKE or ILIKE - applied to elements of a JSONB[] column.
I can use unnest() to display nested JSONB elements separately, but I am having trouble combining that with my LIKE expression. My query:
SELECT
UNNEST( column_jsonb[] )
FROM
table1
WHERE
UNNEST( column_jsonb[] ) ->> 'member_type' LIKE '%member%'
Results in an error:
argument of WHERE must not return a set
How to get this right?

If it's indeed a jsonb[] column:
SELECT * -- or whatever
FROM t, unnest(jsonb_col) j
WHERE j->>'member_type' LIKE '%member%';
That's an implicit CROSS JOIN LATERAL.
If it's a JSON array in a plain jsonb column (more likely):
SELECT *
FROM t1, jsonb_array_elements(jsonb_col) j
WHERE j->>'member_type' LIKE '%member%';
Related:
Query for array elements inside JSON type

Related

How to set an array contains value condition with Ruby Sequel?

I have this function that I need to modified to select from elements table the rows in which the column filters(array type) contain the feature_id param
def get_categories_by_company_and_feature(company_id:,feature_id:)
DB[:categories]
.where(company_id: company_id)
.join(:elements, category_id: :id)
.order(:category_name, :element_name)
.select_all(:categories, :elements)
.select_append(Sequel[:categories][:user_active].as(:category_user_active),
Sequel[:categories][:id].as(:category_id),
Sequel[:elements][:id].as(:element_id))
end
I've seen documentation with array_op.contains(:a) and many operators< but I don't know how to combine it with this syntax.
Also, what kind of operators can I apply for a column like Sequel[:categories][:user_active]?

How to parse a table with a JSON array field in PostgreSQL into rows?

I have a table that contains a json array. Here is a sample of the contents of the field from:
SELECT json_array FROM table LIMIT 5;
Result:
[{"key1":"value1"}, {"key1":"value2"}, ..., {"key2":"value3"}]
[]
[]
[]{"key1":"value1"}
[]
How can I retrieve all the values and count how many of each value was found?
I am using PostgreSQL 9.5.14, and I have tried the solutions here Querying a JSON array of objects in Postgres
and the ones suggested to me by another generous stackoverflow user in my last question: How can I parse JSON arrays in postgresql?
I tried:
SELECT
value -> 'key1'
FROM
table,
json_array_elements(json_array);
which sadly does not work for me due to receiving the error: cannot call json_array_elements on a scalar
This error happens when using a query that returns more than one row or more than one column as a scalar subquery.
Another solution I tried was:
SELECT json_array as json, (json_array->0),
coalesce(
case
when (json_array->0) IS NULL then null
else (json_array->0->>'key1')
end,
'No value') AS "Value"
FROM table;
which only returned null values for the "Value"
Referencing Querying a JSON array of objects in Postgres I attempted to use this solution as well:
WITH json_test (col) AS (
values (json_arrays)
)
SELECT
y.x->'key1' "key1"
FROM json_test jt,
LATERAL (SELECT json_array_elements(jt.col) x) y;
But I would need to be able to fit all the elements of the json_arrays into json_test
So far I have only attempted to list all the values in the all json arrays, but my ideal end-result for the query resembles this:
Value | Amount
---------------
value1 | 48
value2 | 112
value3 | 93
value4 | 0
Yet again I am grateful for any help with this, thank you in advance.
step-by-step demo:db<>fiddle
SELECT
each.value,
COUNT(*)
FROM
data,
json_array_elements(json_array) elems, -- 1
json_each_text(elems) each -- 2
GROUP BY each.value -- 3
Expand array into one row for each array element
split the key/value pairs into two columns
group by the new value column/count

Access the index of an element in a jsonb array

I would like to access the index of an element in a jsonb array, like this:
SELECT
jsonb_array_elements(data->'Steps') AS Step,
INDEX_OF_STEP
FROM my_process
I don't see any function in the manual for this.
Is this somehow possible?
Use with ordinality. You have to call the function in the from clause to do this:
with my_process(data) as (
values
('{"Steps": ["first", "second"]}'::jsonb)
)
select value as step, ordinality- 1 as index
from my_process
cross join jsonb_array_elements(data->'Steps') with ordinality
step | index
----------+-------
"first" | 0
"second" | 1
(2 rows)
Read in the documentation (7.2.1.4. Table Functions):
If the WITH ORDINALITY clause is specified, an additional column of type bigint will be added to the function result columns. This column numbers the rows of the function result set, starting from 1.
You could try using
jsonb_each_text(jsonb)
which should supply both the key and value.
There is an example in this question:
Extract key, value from json objects in Postgres
except you would use the jsonb version.

PSQL: Count number of wildcard values in JSONB array

My table has a jsonb column that stores JSON arrays of strings in this format:
["ItemA", "ItemB", "ItemC"]
I'm trying to filter the rows based on the number of certain items in the array, using a wildcard for a part of the name of the item.
From what I have read here on SO, I could use the jsonb_to_recordset function and then just query the data normally, but I can't put the pieces together.
How do I use the jsonb_to_recordset to accomplish this? It's asking for a column definition list, but how do I specify one for just a string array?
My hypothetical (but of course not valid) query would look something like this:
SELECT * FROM mytable, jsonb_to_recordset(mytable.jsonbdata) AS text[] WHERE mytable.jsonbdata LIKE 'Item%'
EDIT:
Maybe it could be done using something like this instead:
SELECT * FROM mytable WHERE jsonbdata ? 'Item%';
Use jsonb_array_elements():
select *
from
mytable t,
jsonb_array_elements_text(jsonbdata) arr(elem)
where elem like 'Item%';
jsonbdata | elem
-----------------------------+-------
["ItemA", "ItemB", "ItemC"] | ItemA
["ItemA", "ItemB", "ItemC"] | ItemB
["ItemA", "ItemB", "ItemC"] | ItemC
(3 rows)
Probably you'll want to select only distinct table rows:
select distinct t.*
from
mytable t,
jsonb_array_elements_text(jsonbdata) arr(elem)
where elem like 'Item%';

postgres comparing varying character with array from string_to_array

I'm having problems comparing Postgres types, and would be grateful for some help. I am extracting valid document types from a configuration table that holds a tilda-separated string, as follows:
SELECT string_to_array(value,'|') as document_kinds
FROM company_configs
WHERE option = 'document_kinds'
this gives me an array of values, so
'doc1|doc2|doc3' becomes {doc1,doc2,doc3}
Next I need to select the documents for a given person which match my document types:
SELECT * FROM people
JOIN documents ON ...
WHERE kind IN
(SELECT string_to_array(value,'|') as document_kinds
FROM company_configs
WHERE option = 'document_kinds')
the documents.kind column is 'character varying'
my understanding is that string_to_array is producing an array of text values 'text[]'
This query produces the error 'ERROR: operator does not exist: character varying = text[]'
If I cast 'kind' into text, with
SELECT * FROM people
JOIN documents ON ...
WHERE kind::text IN
(SELECT string_to_array(value,'|') as visa_document_kinds FROM languages_united.company_configs WHERE option = 'visa_document_kinds')
I get the error 'ERROR: operator does not exist: text = text[]'
I'm not sure how to compare the two, and would be grateful for any advice.
Thanks in advance
Dan
Postgres 9.4.1
You can select against any array element by using the ANY operator, if your sub-query returns exactly one row:
SELECT *
FROM people
JOIN documents ON ...
WHERE kind = ANY (
SELECT string_to_array(value,'|') as document_kinds
FROM company_configs
WHERE option = 'document_kinds');
If the sub-query possibly returns multiple rows, you can use the regexp_split_to_table() function:
SELECT *
FROM people
JOIN documents ON ...
JOIN (
SELECT document_kinds
FROM company_configs,
regexp_split_to_table(value, '\|') as document_kinds
WHERE option = 'document_kinds') sub ON sub.document_kinds = kind;
(You will have to tweak this to match the rest of your query.)

Resources