在SQLAlchemy中过滤大关系子查询

时间:2019-02-25 09:27:50

标签: python python-3.x sqlalchemy

考虑具有关系的简单SQLAlchemy模型:

class User(Base):

    __tablename__ == 'users'

    friends = relationship('User', secondary=friend,
        primaryjoin=id == friend.c.to_id,
        secondaryjoin=id == friend.c.from_id,
        order_by=friends.c.id,
        lazy='subquery')

在某些病理情况下,用户可能有很多朋友,因此此查询非常昂贵:

user_friends = user.friends

如何执行相同的子查询,例如请求特定的order_by并限制为N个对象?我想做类似的事情:

some_friends = user.friends.order_by('some_field').limit(10)

但是我从文档中无法理解如何在子查询中配置这些查询选项

停止将此问题标记为重复问题,所谓的重复问题与处理子查询无关。

2 个答案:

答案 0 :(得分:1)

根据@malan的建议,如果不需要lazy='dynamic',则使用subquery是这种情况的最简单解决方案。

答案 1 :(得分:1)

如果有问题的DBMS支持窗口功能,则似乎较新的SQLAlchemy版本(1.3及更高版本)已经引入了一种创建这种关系using AliasedClass and window functions的方法:

class User(Base):
    ...

top_friends = select([
        User,
        friend.c.to_id,
        func.row_number().over(partition_by=friend.c.to_id, 
                               order_by=User.some_field).label('index')]).\
    select_from(join(User, friend, User.id == friend.c.from_id)).\
    alias()

friend_user = aliased(User, top_friends)

User.friends = relationship(
    friend_user,
    primaryjoin=and_(User.id == top_friends.c.to_id, top_friends.c.index <= 10))