85

I have a column named params in a table named reports which contains JSON.

I need to find which rows contain the text 'authVar' anywhere in the JSON array. I don't know the path or level in which the text could appear.

I want to just search through the JSON with a standard like operator.

Something like:

SELECT * FROM reports
WHERE params LIKE '%authVar%'

I have searched and googled and read the Postgres docs. I don't understand the JSON data type very well, and figure I am missing something easy.

The JSON looks something like this.

[  
   {  
      "tileId":18811,
      "Params":{  
         "data":[  
            {  
               "name":"Week Ending",
               "color":"#27B5E1",
               "report":"report1",
               "locations":{  
                  "c1":0,
                  "c2":0,
                  "r1":"authVar",
                  "r2":66
               }
            }
         ]
      }
   }
]

1 Answer 1

168

In Postgres 11 or earlier it is possible to recursively walk through an unknown json structure, but it would be rather complex and costly. I would propose the brute force method which should work well:

select *
from reports
where params::text like '%authVar%';
-- or 
-- where params::text like '%"authVar"%';
-- if you are looking for the exact value

The query is very fast but may return unexpected extra rows in cases when the searched string is a part of one of the keys.

In Postgres 12+ the recursive searching in JSONB is pretty comfortable with the new feature of jsonpath.

Find a string value containing authVar:

select *
from reports
where jsonb_path_exists(params, '$.** ? (@.type() == "string" && @ like_regex "authVar")')

The jsonpath:

$.**                     find any value at any level (recursive processing)
?                        where
@.type() == "string"     value is string
&&                       and
@ like_regex "authVar"   value contains 'authVar'

Or find the exact value:

select *
from reports
where jsonb_path_exists(params, '$.** ? (@ == "authVar")')

Read in the documentation:

Sign up to request clarification or add additional context in comments.

10 Comments

What would be the advantage of recursively walking through?
This tutorial explains the "params::text" in detail: postgresqltutorial.com/postgresql-cast
@CaleSweeney - This simple solution will fail when we're searching for an attribute which is the same as one of keys.
Is there a way to use "jsonb_path_exists" with multiple params and case insensitive?
@ersu - yes, read 9.15.2.2. Regular Expressions in the docs.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.