Reputation: 745
I have a jsonb "contacts" field in a table which is:
Example:
{
"main": [{
"name": "Bobby Smith",
"email": "[email protected]",
"telephone": "555-999-0000"
}, {
"name": "Joan Smith",
"email": "[email protected]",
"telephone": "555-999-0002"
}],
"billing": [{
"name": null,
"region": "Arizona",
"address": ["PO BOX 123", "456 Nowhere Road"],
"country": "USA",
"locality": "BigMac",
"postalCode": "90210"
}],
"emergency": [{
"name": "John Cooper",
"email": "[email protected]",
"telephone": "555-987-0000"
}]
}
I'd like to have a simple way to do a comparison on say the name fields that is agnostic to the keys in the outermost object, as well as the number of elements in each array.
Effectively this: SELECT * FROM clients WHERE contacts#>>'{*, *, name}' = 'John Cooper';
Would return the row containing the above as it matches '{emergency, 0, name}'
Upvotes: 0
Views: 1917
Reputation: 36234
You need to unwind data for your current database design, like:
select t.*
from t, jsonb_each(contacts) e, jsonb_array_elements(e.value) c
where c ->> 'name' = 'John Cooper'
But this can't use any index for your query.
A better design would be to only store contact data on each row in a joining table, like:
t t_contact
------------------ -------------------------
t_id primary key t_id references t(t_id)
contact_type text
contact jsonb
Then, you could index t_contact(contact)
and query, like:
select t.*
from t
join t_contact using (t_id)
where contact ->> 'name' = 'John Cooper'
group by t.t_id
Upvotes: 2