I'm using sqlalchemy's ORM, and run queries like, I want to get all Odds 
for a specific Event.

An Event has many EventMarkets, an EventMarket has many MarketParticipants, 
and each MarketParticipant has many Odds.

A query like,


Odds.query
> .join(Odds.market_participant)
> .join(MarketParticipant.event_market)
> .join(EventMarket.event)
> .options( 

    contains_eager(Odds.market_participant)
>     .contains_eager(MarketParticipant.event_market)
>     .contains_eager(EventMarket.event))
> .filter(Event.id == 123456)


This produces a query like,

SELECT ...
>  FROM odds
>  LEFT OUTER JOIN market_participant AS market_participant_1 ON 
> market_participant_1.id = odds.market_participant_id 
>  LEFT OUTER JOIN event_market AS event_market_1 ON event_market_1.id = 
> market_participant_1.event_market_id 
>  LEFT OUTER JOIN event AS event_1 ON event_1.id = event_market_1.event_id
>
WHERE event.id = 123456
>

Which works perfectly, but I consider having to have both join and 
contains_eager redundant, I'd much prefer to do the more straightforward,

Odds.query
> .options( 

    joinedload(Odds.market_participant)
>     .joinedload(MarketParticipant.event_market)
>     .joinedload(EventMarket.event))
> .filter(Event.id == 123456)


But this produces a query like

SELECT ...
>  FROM event, odds
>  LEFT OUTER JOIN market_participant AS market_participant_1 ON 
> market_participant_1.id = odds.market_participant_id 
>  LEFT OUTER JOIN event_market AS event_market_1 ON event_market_1.id = 
> market_participant_1.event_market_id 
>  LEFT OUTER JOIN event AS event_1 ON event_1.id = event_market_1.event_id
> WHERE event.id = 123456
>

As it queries from both Event, and then Odds with the joins to Event again, 
this time as "event_1", it joins the entire table, incorrectly.

----

I'm also aware I could do all the filters,

Odds.query
> .filter(
>     Odds.market_participant,
>     MarketParticipant.event_market,
>     EventMarket.event,
>     Event.id == 123456)
>
>
But that doesn't ensure the "bits" are loaded in (market_participant for 
odds, event_market for market_participant, etc.), you still need to 
redundantly add the contains_eager chain,

Odds.query
> .options(contains_eager(Odds.market_participant)
>          .contains_eager(MarketParticipant.event_market)
>          .contains_eager(EventMarket.event))
> .filter(
>     Odds.market_participant,
>     MarketParticipant.event_market,
>     EventMarket.event,
>     Event.id == 123456)
>
>
This produces a perfectly acceptable query, with filtering via the tables, 
instead of joins,

SELECT ... 
>
FROM event, event_market, market_participant, odds
>  WHERE market_participant.id = odds.market_participant_id 

 AND event_market.id = market_participant.event_market_id 
>  AND event.id = event_market.event_id 

 AND event.id = 123456

 
----

Again, I know coupling join with contains_eager (as is done in the first 
example) works, but I absolutely consider it redundant.

This redundancy is shown more clearly if you swap contains_eager with 
joinedload,

Odds.query
> .join(Odds.market_participant)
> .join(MarketParticipant.event_market)
> .join(EventMarket.event)
> .options( 

     joinedload(Odds.market_participant)
>     .joinedload(MarketParticipant.event_market)
>     .joinedload(EventMarket.event))
> .filter(Event.id == 123456)


That produces the exact same as the first query, coupling join with 
contains_eager.

----

Is there any way to be able to specify what you want in joinedload in the 
options without having to specify the join as well, *AND* be able to filter 
on those tables, like the example.

The main reason I'm asking this is because every now and again, with a 
simple autcompleted typo, or forgetfulness, I forget something, or get 
something wrong in the join chain, or the contains_eager chain, and instead 
of a query coming back within seconds, it stalls for a few minutes, trying 
to return a million rows, instead of fifty.  99% of the time with these 
mistakes one side will be correct (the join chain), with a mistake in the 
other (the contains_eager chain).  I understand those bugs / errors are "on 
me", but even every time I do it, to do it right it frustrates me a bit.

I've put a decent amount of effort into design the tables with minimal 
redundancy, both on the Db side, and within my code, but then, when I'm 
running a few queries, I do get frustrated every time when I have to write 
double the "join" logic, in both .join / .filter, and .contains_eager.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to