Dra*_*mon 10 python sql sqlalchemy
我是sqlalchemy的新手,虽然文档似乎相当彻底,但我找不到一种方法来做我想要的.
说我有两张桌子:论坛和帖子.每个论坛都有一个家长论坛和任意数量的帖子.我想要的是:
所以我开始:
query(Forum).filter(Forum.parent==None).all()
Run Code Online (Sandbox Code Playgroud)
这给了我所有顶级论坛.当然,访问子论坛会产生n个选择查询.
query(Forum).options(eagerload('children')).filter(Forum.parent==None).all()
Run Code Online (Sandbox Code Playgroud)
这解决了n选择问题.
现在我最好的猜测是这样的:
query(Forum, func.count(Forum.children.posts)).options(eagerload('children')).filter(Forum.parent==None).group_by(Forum.children.id).all()
Run Code Online (Sandbox Code Playgroud)
但我得到的只是:
AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object has an attribute 'posts'
Run Code Online (Sandbox Code Playgroud)
我尝试了一些变化,但没有进一步.为了清楚起见,我正在寻找相当于这个SQL:
select Forum.*, Child.*, count(Post.id)
from Forum
left join Forum Child on Child.parent = Forum.id
left join Message on Message.forum = Child.id
where Forum.parent is null
group by Child.id
Run Code Online (Sandbox Code Playgroud)
因为您希望可以在子论坛对象上访问帖子计数,所以在设置映射器时您需要将其声明为列属性.列属性声明应该类似于这样(假设您使用声明性):
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)
Run Code Online (Sandbox Code Playgroud)
然后你可以这样说出你的查询:
query(Forum).filter_by(parent=None).options(
eagerload('children'),
undefer('children.post_count'))
Run Code Online (Sandbox Code Playgroud)
另一种选择是选择孩子并单独计数.在这种情况下,您需要自己进行结果分组:
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)
)
from itertools import groupby
from operator import attrgetter
for forum, childforums in groupby(q, key=attrgetter('Node')):
for _, child, post_count in childforums:
if child is None:
# No children
break
# do something with child
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4759 次 |
| 最近记录: |