WITH pets AS (SELECT 'Dog' AS mainpet, '
[
{
"petSpecies": "Dog",
"mainMeal": "Meat"
},
{
"petSpecies": "Cat",
"mainMeal": "Milk"
},
{
"petSpecies": "Lizard",
"mainMeal": "Insects"
}
]'::jsonb AS petfood)
SELECT pets.petfood,
jsonb_path_query_first(pets.petfood, '$[*]?(@."petSpecies" == "Dog")."mainMeal"') ->> 0 AS mypetmainmeal
FROM pets
Instead of filtering on "petSpecies" == "Dog"
, I want to filter on "petSpecies" == pets.mainpet
(i.e. a value from another column), but I'm struggling with the syntax.
I tried this but it doesn't work:
jsonb_path_query_first(pets.petfood, '$[*]?(@."petSpecies" == "' || pets.mainpet || '")."mainMeal"') ->> 0
Grateful for any help.
The jsonb_path_query_x()
functions accept an optional vars
parameter. There's no need to concatenate the JSONPath expression, you can pass things in through there.
demo at db<>fiddle
select pets.petfood
, jsonb_path_query_first( pets.petfood
,'$[*]?(@."petSpecies" == $some_var)."mainMeal"'
,jsonb_build_object('some_var',pets.mainpet)) ->>0
from pets;
petfood | mypetmainmeal |
---|---|
[{"mainMeal": "Meat", "petSpecies": "Dog"}, {"mainMeal": "Milk", "petSpecies": "Cat"}, {"mainMeal": "Insects", "petSpecies": "Lizard"}] | Meat |
That being said, your idea would've worked if you parenthesised the expression you constructed, then cast it to ::jsonpath
select pets.petfood
, jsonb_path_query_first(
pets.petfood
,('$[*]?(@."petSpecies"=='||to_json(pets.mainpet)::text||')."mainMeal"')::jsonpath
) ->> 0 as mypetmainmeal
from pets;
Also note the to_json()::text
suggested by @Bergi below, that handles proper quoting and escaping automatically.
Without that explicit ::jsonpath
cast, the concatenation operators ||
give you a text
-type value, leading to function signature mismatch:
ERROR: function jsonb_path_query_first(jsonb, text) does not exist LINE 2: , jsonb_path_query_first( ^ HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Without the text
-type-returning concatenation operators or the cast, that single-quoted parameter was initially just an unknown
-type string constant which is subject to automatic type conversion rules, which automatically converted it to jsonpath
. Using the ||
operators in your second example made it a text
, disabling that. Explicit cast also disables that auto-conversion, but it isn't needed any longer because that makes it match the function signature directly.