Oh, thank you so much for such an elaborate reply! The "groupby method" 
totally suits me.

On Sunday, April 5, 2015 at 6:17:35 PM UTC+3, Michael Bayer wrote:
>
>  
>
> On 4/5/15 8:46 AM, Yegor Roganov wrote:
>  
> Given the User-Addresses schema as in the docs, I need to select all users 
> along with only those email addresses which end with "@gmail.com".
> The question is how do I group these filtered emails by user?
> Apparently I can use `contains_eager` to write something like this:
>
>     
> session.query(User).outerjoin(User.addresses).filter(Address.email_address.like('%@
> gmail.com'))\
>                 .options(contains_eager(User.addresses))
>  
>  But having the filtered email addresses on the `addresses` attribute is 
> rather confusing.
>  
>
> I agree, this is not the typical case you'd use it.
>
>
> I'd like to either:
>   1. iterate a query results in a clear way:
>          for user, gmail_addrs in session.query(???)
>  
> sure, just say session.query(User, Address).outerjoin(...) and that's what 
> you get.    But this is a product result; if User "A" has three addresses, 
> you get User "A" back three times, one for each address.   This is just 
> plain SQL behavior.
>
>
>    2. get the filtered children attached to a different field (smth like 
> `contains_eager(User.addresses, attach_to='_gmail_addrs')`)
>  
>
> right, a "nested" result but not attached to the User.addresses 
> attribute.   There was a database that did this, and I even wrote a 
> SQLAlchemy ORM driver for it, but unfortunately it's called FoundationDB 
> and it doesn't seem to exist any more :).    
>
> There isn't a specific option on contains_eager() like that because the 
> mechanics of mapped attributes on mapped classes is not really 
> "lightweight" enough for that operation to be appropriate in that way; it 
> could be possible, that something like contains_eager() loading could apply 
> things to simple instance-only collections that aren't relationships, but 
> this isn't something built in right now.
>  
> However, if you want to group the User, Address objects, use plain 
> Python.    In this case itertools.groupby will give you what you need as a 
> one liner, assuming the User rows for a given identifier are contiguous 
> (which is always the case for simple joins, or an order_by() guarantees it):
>
> import itertools
> q = session.query(User, 
> Address).outerjoin(User.addresses).filter(Address.email.like('%@gmail.com
> ')).order_by(User.id)
>
> for user, collection in itertools.groupby(q, key=lambda row: row[0]):
>     addresses = (row[1] for row in collection if row is not None)
>     
>
>
>
>
>
>
>
>
>
>
>
>
>  
> Thanks.
>  -- 
> 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 [email protected] <javascript:>.
> To post to this group, send email to [email protected] 
> <javascript:>.
> Visit this group at http://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.
>
>
>  
On Sunday, April 5, 2015 at 6:17:35 PM UTC+3, Michael Bayer wrote:
>
>  
>
> On 4/5/15 8:46 AM, Yegor Roganov wrote:
>  
> Given the User-Addresses schema as in the docs, I need to select all users 
> along with only those email addresses which end with "@gmail.com".
> The question is how do I group these filtered emails by user?
> Apparently I can use `contains_eager` to write something like this:
>
>     
> session.query(User).outerjoin(User.addresses).filter(Address.email_address.like('%@
> gmail.com'))\
>                 .options(contains_eager(User.addresses))
>  
>  But having the filtered email addresses on the `addresses` attribute is 
> rather confusing.
>  
>
> I agree, this is not the typical case you'd use it.
>
>
> I'd like to either:
>   1. iterate a query results in a clear way:
>          for user, gmail_addrs in session.query(???)
>  
> sure, just say session.query(User, Address).outerjoin(...) and that's what 
> you get.    But this is a product result; if User "A" has three addresses, 
> you get User "A" back three times, one for each address.   This is just 
> plain SQL behavior.
>
>
>    2. get the filtered children attached to a different field (smth like 
> `contains_eager(User.addresses, attach_to='_gmail_addrs')`)
>  
>
> right, a "nested" result but not attached to the User.addresses 
> attribute.   There was a database that did this, and I even wrote a 
> SQLAlchemy ORM driver for it, but unfortunately it's called FoundationDB 
> and it doesn't seem to exist any more :).    
>
> There isn't a specific option on contains_eager() like that because the 
> mechanics of mapped attributes on mapped classes is not really 
> "lightweight" enough for that operation to be appropriate in that way; it 
> could be possible, that something like contains_eager() loading could apply 
> things to simple instance-only collections that aren't relationships, but 
> this isn't something built in right now.
>  
> However, if you want to group the User, Address objects, use plain 
> Python.    In this case itertools.groupby will give you what you need as a 
> one liner, assuming the User rows for a given identifier are contiguous 
> (which is always the case for simple joins, or an order_by() guarantees it):
>
> import itertools
> q = session.query(User, 
> Address).outerjoin(User.addresses).filter(Address.email.like('%@gmail.com
> ')).order_by(User.id)
>
> for user, collection in itertools.groupby(q, key=lambda row: row[0]):
>     addresses = (row[1] for row in collection if row is not None)
>     
>
>
>
>
>
>
>
>
>
>
>
>
>  
> Thanks.
>  -- 
> 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 [email protected] <javascript:>.
> To post to this group, send email to [email protected] 
> <javascript:>.
> Visit this group at http://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.
>
>
>  
On Sunday, April 5, 2015 at 6:17:35 PM UTC+3, Michael Bayer wrote:
>
>  
>
> On 4/5/15 8:46 AM, Yegor Roganov wrote:
>  
> Given the User-Addresses schema as in the docs, I need to select all users 
> along with only those email addresses which end with "@gmail.com".
> The question is how do I group these filtered emails by user?
> Apparently I can use `contains_eager` to write something like this:
>
>     
> session.query(User).outerjoin(User.addresses).filter(Address.email_address.like('%@
> gmail.com'))\
>                 .options(contains_eager(User.addresses))
>  
>  But having the filtered email addresses on the `addresses` attribute is 
> rather confusing.
>  
>
> I agree, this is not the typical case you'd use it.
>
>
> I'd like to either:
>   1. iterate a query results in a clear way:
>          for user, gmail_addrs in session.query(???)
>  
> sure, just say session.query(User, Address).outerjoin(...) and that's what 
> you get.    But this is a product result; if User "A" has three addresses, 
> you get User "A" back three times, one for each address.   This is just 
> plain SQL behavior.
>
>
>    2. get the filtered children attached to a different field (smth like 
> `contains_eager(User.addresses, attach_to='_gmail_addrs')`)
>  
>
> right, a "nested" result but not attached to the User.addresses 
> attribute.   There was a database that did this, and I even wrote a 
> SQLAlchemy ORM driver for it, but unfortunately it's called FoundationDB 
> and it doesn't seem to exist any more :).    
>
> There isn't a specific option on contains_eager() like that because the 
> mechanics of mapped attributes on mapped classes is not really 
> "lightweight" enough for that operation to be appropriate in that way; it 
> could be possible, that something like contains_eager() loading could apply 
> things to simple instance-only collections that aren't relationships, but 
> this isn't something built in right now.
>  
> However, if you want to group the User, Address objects, use plain 
> Python.    In this case itertools.groupby will give you what you need as a 
> one liner, assuming the User rows for a given identifier are contiguous 
> (which is always the case for simple joins, or an order_by() guarantees it):
>
> import itertools
> q = session.query(User, 
> Address).outerjoin(User.addresses).filter(Address.email.like('%@gmail.com
> ')).order_by(User.id)
>
> for user, collection in itertools.groupby(q, key=lambda row: row[0]):
>     addresses = (row[1] for row in collection if row is not None)
>     
>
>
>
>
>
>
>
>
>
>
>
>
>  
> Thanks.
>  -- 
> 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 [email protected] <javascript:>.
> To post to this group, send email to [email protected] 
> <javascript:>.
> Visit this group at http://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.
>
>
>  

-- 
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to