Reputation: 365
I have a base query and need to add a filter for locations.
Location.parents
is an array of integers.
It works, but it uses 2 queries:
parents_ids = self._db_session.query(Location.parents)\
.filter(Location.id == location_id)\
.scalar()
query = query.filter(
or_(
BookingItem.location_id == location_id,
BookingItem.location_id.in_(parents_ids)
)
)
How can I do this with one query? I tried to use a subquery, but it doesn't work.
parents_ids = self._db_session.query(Location.parents)\
.filter(Location.id == location_id)\
.subquery()
query = query.filter(
or_(
BookingItem.location_id == location_id,
BookingItem.location_id.in_(parents_ids.as_scalar())
)
)
Upvotes: 0
Views: 49
Reputation: 13129
If you want the SQL to look like this:
SELECT id
FROM booking_item
WHERE location_id = ?
OR (SELECT location_id = ANY(parents) FROM location WHERE id = ?)
Then the related SQLAlchemy would be
parents_ids = self._db_session\
.query(BookingItem.location_id == Location.parents.any())\
.filter(Location.id == location_id)\
.subquery()
query = query.filter(
or_(
BookingItem.location_id == location_id,
parents_ids.as_scalar()
)
)
Another option is to use UNNEST
to create a list of options:
SQL:
SELECT id
FROM booking_item
WHERE location_id = ?
OR location_id IN (SELECT UNNEST(parents) FROM location WHERE id = ?)
Then the related SQLAlchemy would be
parents_ids = self._db_session\
.query(func.unnest(Location.parents))\
.filter(Location.id == location_id)\
.subquery()
query = query.filter(
or_(
BookingItem.location_id == location_id,
BookingItem.location_id.in_(parents_ids.as_scalar())
)
)
Upvotes: 1