Pagination SQLAlchemy多对多左外部连接与已排序的实体列表

Pagination SQLAlchemy多对多左外部连接与已排序的实体列表,pagination,sqlalchemy,many-to-many,left-join,Pagination,Sqlalchemy,Many To Many,Left Join,我有两张表:常驻和过敏原,以及两者之间的多对多关系。通过使用SQLAlchemy而不是PostgreSQL,我想按过敏原的字母顺序排列居民名单: resident_id | resident_name | allergs -------------+---------------+-------------------- 1 | John | {milk,pollen,soy} 3 | Hopkins

我有两张表:常驻和过敏原,以及两者之间的多对多关系。通过使用SQLAlchemy而不是PostgreSQL,我想按过敏原的字母顺序排列居民名单:

 resident_id | resident_name |      allergs       
-------------+---------------+--------------------
           1 | John          | {milk,pollen,soy}
           3 | Hopkins       | {pollen,stupidity}
           2 | Mary          | {stupidity}
           4 | Lee           | {NULL}
我知道这可以在PostgreSQL中使用array_agg实现:

选择
resident.id作为resident_id,
resident.name作为resident\u name,
数组_agg(过敏原名称按过敏原名称排序)作为过敏原
来自居民
左外连接(常驻过敏原作为常驻过敏原1
加入过敏原
关于过敏原id=居民\过敏原\ 1.过敏原\ id)
ON resident.id=resident\u过敏原\u 1.resident\u id
按居民id分组
按过敏原排序
但据我所知,SQLAlchemy在array_agg函数中不支持ORDER BY子句

到目前为止,我已经尝试:

  • db.session.query(常驻).outerjoin(常驻.过敏原).order_by(过敏原.名称).from_self().group_by(常驻)
    ,但这并不能正确排序过敏原
  • db.session.query(Resident,func.row_number().over(order_by=Allergen.name)。label('rownum'))。outerjoin(Resident.allergies)。order_by(Allergen.name)。from_self(Resident,func.min('rownum')。label('maxrownum'))。group_by(Resident)。order_by('maxrownum')。from_self(Resident)
    ,但
    func.min('rownum'))
    返回
    u'rownum'
    而不是引用列
  • 获取过敏原分类列表,加入居民,然后按居民或不同居民分组,但这破坏了顺序
下表定义:

resident_过敏原=db.表(
“居民过敏原”,
db.Column('resident_id',db.Integer,db.ForeignKey('resident.id'),nullable=False,index=True),
db.Column('allogen_id',db.Integer,db.ForeignKey('allogen.id'),nullable=False,index=True),
UniqueConstraint('resident_id'、'allergen_id'))
过敏原类别(db.型号):
id=列(db.Integer,主键=True)
名称=列(db.String)
定义初始化(self,name):
self.name=名称
类驻留(db.Model):
id=列(db.Integer,主键=True)
名称=列(db.String)
过敏=db.关系(“过敏原”,
集合类=集合,
次级=居民过敏原,
backref=db.backref('residents',lazy='lazy'))
定义初始化(self,name):
self.name=名称
如果相关的话,我使用的是
SQLAlchemy 0.8.5
而不是
postgresql9.3

使用SQLAlchemy,我能够添加我自己版本的array\u agg,并通过以下方式支持订购:

从sqlalchemy.ext.compiler导入编译
从sqlalchemy.sql.expression import ColumnClause中,_literal_as_binds
类数组_agg(ColumnClause):
“”“自定义版本的PostgreSQL数组\u agg,支持ORDER BY。
用法:…..订购者(数组\u agg(过敏原名称,订购者=过敏原名称))
"""
定义初始化(self、expr、order\u by=None):
self.expr=\u literal\u as\u binds(expr)
self.order\u by=\u literal\u as\u binds(order\u by)
@财产
来自对象(自身)的定义:
从对象返回self.expr.\u
@编译(数组_agg)
def compile_array_agg(元素,编译器,**kwargs):
head='数组\u聚集(%s'%(
编译器.process(element.expr),
)
如果element.order_by不是无:
tail='ORDER BY%s'%compiler.process(element.ORDER_BY)
其他:
尾=')'
返回头+尾