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 } } ] } } ]
Querying JSON dataPostgreSQL provides two native operators -> and ->> to help you query JSON data. The operator -> returns JSON object field by key. The operator ->> returns JSON object field by text.
To query JSON data, you can use standard T-SQL. If you must create a query or report on JSON data, you can easily convert JSON data to rows and columns by calling the OPENJSON rowset function. For more information, see Convert JSON Data to Rows and Columns with OPENJSON (SQL Server).
You can save any valid json value to either json or to a jsonb column. But you cannot bind it as string/ text / varchar , if you use prepared statements (use casts instead in sql, like UPDATE ... SET json_col = $1::json or bind it as unknown ).
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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With