![](/img/trans.png)
[英]SQLAlchemy: Iterate over each subset of a query result set partitioned by ordering parameters
[英]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.