2

I want to select all products that have active shipments (those have one or more shipment_ids in shipments table).

My product table has a jsonb column called data like this:

{
 "name": "foo",
 "shipments": [1,2,5,7]
}

I thought it would be as simple as something like to this:

... where shipment.id IN (products.data->'shipments')

or

... where shipment.id = any(products.data->'shipments')

but it is not.

After some digging I have managed to get it working, but I do not know if that is the simplest and most efficient solution for this:

select "products".* from "products"
 cross join LATERAL (
 select array_agg(ps.shipment::int) as ids
 from jsonb_array_elements(products.data -> 'shipments') as ps(shipment)
 ) ps
 where exists(select from shipments as "sh" where sh.id = any (ps.ids))
order by id

So do I actually need that cross join? Or there is a way to simply cast the JSON array to a Postgres integer array?

Laurenz Albe
61.9k4 gold badges57 silver badges92 bronze badges
asked Jul 3, 2019 at 11:11

1 Answer 1

2

You can do it like this:

SELECT *
FROM products
WHERE EXISTS (
 SELECT 1 FROM shipment
 WHERE products.data @>
 jsonb_build_object('shipments', ARRAY[shipment.id])
 );

This query is still complicated and not very efficient.

The reason for that is the terrible data model. JSON in the database can be useful, but just stuffing all your data into a JSON column is a certain recipe for complicated and slow queries.

You should implement this with a junction table that implements the m-to-n relationship between the tables.

My rule of thumb is that you should use JSON in the database only for columns that are not used a lot inside the database.

answered Jul 3, 2019 at 12:14

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.