I’ve the following dataset
Table 1
-------
Id | JsonB
1 | [ { "Name": "ABC" }, { "Name": "DEF" } ]
2 | [ { "Name": "XYZ" }, { "Name": "ABC" } ]
3 | [ { "Name": "GHI" }, { "Name": "JKL" } ]
I want to return the index of the value in search. For example when searching for {"Name": "ABC"}
it would return the below result. Note: my search is on a unique property, however just in case if there are more than one occurrence it can return an array of indexes.
Query result
--------------------
Id | Index
1 | [0]
2 | [1]
3 | null or []
EDIT: because Postgresql works with paths and in case of nested search, may it’s better to return the path instead, but I am happy with any
Query result
--------------------
Id | Path
1 | ['{0}']
2 | ['{1}']
3 | null or []
3
Answers
If you want the result as a JSON array, not a PostgreSQL array, you could use
jsonb_array_elements()
unnests the JSON array andWITH ORDINALITY
gibes us the position in the array.You can use
jsonb_array_elements
with ordinality to get the position of each element :Demo here
You can use the
jsonb_array_elements
table function to extract the objects to match against and theWITH ORDINALITY
option to generate an index. Put them in a subquery and aggregate the indices of the matched objects back into an array:(online demo)
Notice I’ve used
ord - 1
to make the index 0-based, ordinality (and array indexing) is 1-based in Postgres.If there is no match,
array_agg
will returnNULL
, to get an empty array instead, wrap the subquery inARRAY(…)
. Or if you want a json array, useCOALESCE((SELECT json_agg(…) FROM …), '[]')
.