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
Post a Comment