简体   繁体   中英

SQLAlchemy: Filtering across many-to-many yet returning all results

Starting from the many-to-many Blog and Tag model and query from Querying a many-to-many relationship in SQLAlchemy , I know that session.query(Blog).join(Blog.tags).options(contains_eager(Blog.tags)).filter(Blog.tags.in_(list_of_relevant_tags)).all() will give me all the blog posts that have at least one of the tags in list_of_relevant_tags , and those tags will already have been queried and returned.

The potential problem I see (I'm having trouble testing this) is if I want to get a list of the tags on the returned Blogs. I want to return all the tags, but the generated SQL would suggest that, at best, this would require a second query. At worst, SQLA will only return the tags that matched the list.

Is there a way to submit this query in the ORM to return the matching blog posts along with all their tags in one database hit?

I figured something out. It feels like a workaround, though; there's gotta be a more direct way to do this with the ORM.

Basically, you use a subquery of the association table (let's call it BlogTag with columns blog_id and tag_id , that are foreign keys to blogs.id and tags.id , respectively) to generate a list of blog_id s that meet the tag criteria. You then inner join that list of blog_id s to an otherwise-unfiltered query of Blog joined to Tag to return just the relevant Blog s.

t = session.query(BlogTag.blog_id).filter(BlogTag.tag_id.in_(list_of_relevant_tags)).\
    group_by(BlogTag.blog_id).subquery('t')
blogs = session.query(Blog).join(Blog.tags).join(t, t.c.blog_id == Blog.id).\
    options(contains_eager(Blog.tags)).all()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM