繁体   English   中英

SQLAlchemy 递归查询结果集排序

[英]SQLAlchemy recursive query result set ordering

我正在尝试使用 Python (3.9.6) 和 Flask-SqlAlchemy (2.5) 的递归查询来获取分层数据。 这使用自引用数据,其中记录的 parent_id 指向同一表中的另一条记录。 这是我的模型的简化版本:

class Post(db.Model):
    __tablename__ = "post"
    post_id = db.Column(db.String, primary_key=True)
    parent_id = db.Column(db.String, db.ForeignKey("post.post_id"), default=None)
    content = db.Column(db.String)
    children = db.relationship("Post", backref=db.backref("parent", remote_side=[post_id], lazy="joined"))

这是获取帖子及其所有子项的 SQLAlchemy 查询(这使用上下文管理器来确保在范围结束时提交或回滚数据库会话):

    # post_id = unique id of a post in the database
    with db_session_manager() as db_session:
        # build the list of filters here to use in the CTE
        filters = [
            Post.post_id == post_id,
            Post.parent_id == None
        ]
        # construct a self-referential, hierarchal query for the
        # post and it's comments
        posts_hierarchy = (
            db_session.query(Post, literal(0).label('level'))
                .filter(*filters)
                .cte(name='post_hierarchy', recursive=True)
        )
        parent = aliased(posts_hierarchy, name="p")
        children = aliased(Post, name="c")
        posts_hierarchy = (
            posts_hierarchy.union_all(
                db_session.query(Post, (parent.c.level + 1).label("level"))
                .filter(children.parent_id == parent.c.post_id)
                .filter(Post.post_id == children.post_id)
            )
        )         
        posts = (
            db_session.query(Post, posts_hierarchy.c.level)
            .select_entity_from(posts_hierarchy)
            .all()
        )

这在我取回根帖子及其所有子帖子时起作用,但是,结果集包含以下内容:

root post
     1st root child
     2nd root child
     3rd root child
          1st child child (1)
          2nd child child (2)
          3rd child child (3)
          2nd child child (4)

我想回来的是:

root post
     1st root child 
          1st child child (1)
          2nd child child (2)
          3rd child child (3)
     2nd root child
          2nd child child (4)
     3rd root child

etc

我对 SQL 不够了解,无法获得我想要的结果。 我可以尝试什么来解决这个问题?

我已经想出了如何从递归 CTE 查询中获得我想要的。 我像这样修改了数据库表:

class Post(db.Model):
    __tablename__ = "post"
    post_id = db.Column(db.String, primary_key=True)
    parent_id = db.Column(db.String, db.ForeignKey("post.post_id"), default=None)
    sort_key = db.Column(db.String, nullable=False, default=SortKey())
    content = db.Column(db.String)
    children = db.relationship("Post", backref=db.backref("parent", remote_side=[post_id], lazy="joined"))

我添加了 sort_key 列,该列设置为自动递增函数,该函数返回值的字符串版本。 我将递归 CTE SqlAlchemy 查询更新为:

        # build the list of filters here to use in the CTE
        filters = [
            Post.post_uid == post_uid,
            Post.parent_uid == None
        ]
        if current_user.is_anonymous or current_user.can_view_posts():
            filters.append(Post.active == True)

        # build the recursive CTE query
        hierarchy = (
            db_session
                .query(Post, Post.sort_key.label("sorting_key"))
                .filter(*filters)
                .cte(name='hierarchy', recursive=True)
        )
        children = aliased(Post, name="c")
        hierarchy = hierarchy.union_all(
            db_session
                .query(
                    children,
                    (hierarchy.c.sorting_key + " " + children.sort_key).label("sorting_key")
                )
                .filter(children.parent_uid == hierarchy.c.post_uid)
        )
        # query the hierarchy for the post and it's comments
        posts = (
            db_session
                .query(Post, hierarchy.c.sorting_key)
                .select_entity_from(hierarchy)
                .order_by(hierarchy.c.sorting_key)
                .all()
        )

合成sorting_key值是表中sort_key的串联集,用于将结果正确排序为我正在寻找的分层格式。 这是基于这里这里的两个资源。

希望其他人觉得这有帮助

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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