I currently am trying to implement a search based off one of my postgres tables. The type of the column I am searching is jsonb and I am using jsonb_path_exists like the following
select project
from search_table
where jsonb_path_exists(project, '$.** ? (@ like_regex "${searchString}" flag "i")');
Where ${searchString}
is a variable being passed in. This is working great when the json is a string type and I get all the results I would expect. However I cannot figure out how to get this to work if the json field is a number type.
For example if I pass in an ID where in the json it is defined as number, something like id:123456
I would like to be able to pass in 123
and have the object with a value like 123456
being picked up. Basically a 'like' but against a number type. If the id was id:'123456'
it works fine, but since it is a number the current implementation won't pick it up. Is there a way to use jsonb_path_exists
where I can pick up both string and number types with a 'like' type expression?
My current workaround is casting the whole thing to text and searching like that
select project
from search_table
where UPPER(project::text) like UPPER('%${searchString}%')
However, this just seems like an unnecesary step and I would prefer to just search the json values with jsonb_path_exists
. I am using postgres 14.7, any help would be appreciated, thanks.
***UPDATE with min example
CREATE TABLE IF NOT EXISTS dmspgdev.zz_yache_test
(
project_id numeric(19,0),
project jsonb
)
insert into dmspgdev.zz_yache_test
values (1,'{"id":123456, "data":"test1"}');
insert into dmspgdev.zz_yache_test
values (2,'{"id":789323, "data":"search works with string"}');
-- works because data is string
select project
from dmspgdev.zz_yache_test
where jsonb_path_exists(project, '$.** ? (@ like_regex "search" flag "i")');
-- No results because id is number
select project
from dmspgdev.zz_yache_test
where jsonb_path_exists(project, '$.** ? (@ like_regex "456" flag "i")');
You could do it like this:
select project
from dmspgdev.zz_yache_test
where project->>'id' ~~ '%${searchString}%'
or project ->>'data' ~~* '%${searchString}%';
using the operator ilike "~~*" case insensitive LIKE and dividing maters for each of your json fields. Without the need of casting types since the operator "->>" gets the json object field as text.