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