Hi I would like to do a filter with my query using a joinedload. But I can't seem to make it work. Below is my sample query
result = (
session.query(Work).
options(
joinedload(Work.company_users).
joinedload(CompanyUser.user)
).
filter(Work.id == 1).
filter(User.first_name == 'The name'). <<--- I can't get this to work.
all()
)
When running this it's returning a row that is more than what I'm expecting. The real result should only return 8rows. But upon executing this query it returns 234 rows which is way more than what I expect
Joined Load This emits a LEFT OUTER JOIN. Lead object as well as the related object or collection is loaded in one step. from sqlalchemy. orm import joinedload c1 = session. query(Customer).
The sqlalchemy backref is one of the type keywords and it passed as the separate argument parameters which has to be used in the ORM mapping objects. It mainly includes the event listener on the configuration attributes with both directions of the user datas through explicitly handling the database relationships.
The loading of relationships falls into three categories; lazy loading, eager loading, and no loading. Lazy loading refers to objects are returned from a query without the related objects loaded at first.
Use contains_eager() to load back references proactively. This prevents a lazy load to refer back to the parent object, which in turn prevents exceptions when you try to do this when the object is detached from its session.
The reason it is not working is that joinedload
(and all the other relationship loading techniques) are meant to be entirely transparent. That is to say having a joinedload
in your query should not affect it in any other way other than resulting in the relationships being filled. You should read "The Zen of Joined Eager Loading", which begins with:
Since joined eager loading seems to have many resemblances to the use of
Query.join()
, it often produces confusion as to when and how it should be used. It is critical to understand the distinction that whileQuery.join()
is used to alter the results of a query,joinedload()
goes through great lengths to not alter the results of the query, and instead hide the effects of the rendered join to only allow for related objects to be present.
One of the tricks is to use aliases for the joined tables which are not made available. Your query then ends up performing an implicit cross-join between Work and User, and hence the extra rows. So in order to filter against a joined table, use Query.join()
:
session.query(Work).\ join(Work.company_users).\ join(CompanyUser.user).\ filter(Work.id == 1).\ filter(User.first_name == 'The name').\ all()
and if you also need the eagerloads in place, you can instruct the Query that it already contains the joins with contains_eager()
:
session.query(Work).\ join(Work.company_users).\ join(CompanyUser.user).\ options(contains_eager(Work.company_users). contains_eager(CompanyUser.user)).\ filter(Work.id == 1).\ filter(User.first_name == 'The name').\ all()
Note the chained calls to contains_eager()
.
Ok I got it. Just for those who may tackle the same issue what I did was to replace joinedload to contains_eager and added a join. Below is the revise code
result = ( session.query(Work) .join(Work.company_users) .join(CompanyUser.user) .options( contains_eager(Work.company_users) .contains_eager(CompanyUser.user) ) .filter(Work.id == 1) .filter(User.first_name == 'The name') # <<--- Now this to works. .all() )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With