python - How to return the count of related entities in sqlalchemy query -


i'm new sqlalchemy, , while documentation seems thorough, couldn't find way quite want.

say have 2 tables: forum , post. each forum has parent forum, , number of posts. want is:

  • a list of top-level forums
  • eagerly loaded child forums accessible through top-level forums
  • a count of posts each child forum

so started with:

 query(forum).filter(forum.parent==none).all() 

which gives me top level forums. of course accessing child forums yields n select queries.

 query(forum).options(eagerload('children')).filter(forum.parent==none).all() 

this solves n select problem.

now best guess goes this:

 query(forum, func.count(forum.children.posts)).options(eagerload('children')).filter(forum.parent==none).group_by(forum.children.id).all() 

but is:

attributeerror: neither 'instrumentedattribute' object nor 'comparator' object has attribute 'posts' 

i've tried few variations, haven't got further. clarity i'm looking equivalent of sql:

select forum.*, child.*, count(post.id) forum left join forum child on child.parent = forum.id left join message on message.forum = child.id forum.parent null group child.id 

because want post count accessible on child forum objects you'll need declare column property when setting mappers. column property declaration should (assuming use declarative):

forum.post_count = column_property(select([func.count()],         message.__table__.c.forum == forum.__table__.c.id     ).correlate(forum.__table__).as_scalar().label('post_count'),     deferred=true) 

then can phrase query this:

query(forum).filter_by(parent=none).options(     eagerload('children'),     undefer('children.post_count')) 

another option select children , counts separately. in case you'll need result grouping yourself:

childforum = aliased(forum) q = (query(forum, childforum, func.count(message.id))         .filter(forum.parent == none)         .outerjoin((childforum, forum.children))         .outerjoin(childforum.posts)         .group_by(forum, childforum)     )  itertools import groupby operator import attrgetter  forum, childforums in groupby(q, key=attrgetter('node')):     _, child, post_count in childforums:         if child none:             # no children             break         # child 

Comments

Popular posts from this blog

c++ - Convert big endian to little endian when reading from a binary file -

C#: Application without a window or taskbar item (background app) that can still use Console.WriteLine() -

unicode - Are email addresses allowed to contain non-alphanumeric characters? -