Sqlalchemy 以相同的顺序获取结果

Sqlalchemy get results in the same order

我正在使用这个查询

users = User.query.filter(User.id.in_(user_ids)).all()

我想按 user_ids 中的相同顺序获取 users。无论如何,我可以直接在查询中执行此操作,还是必须再次对其进行排序?另外,如果我必须再次对其进行排序,那么基于另一个 ID 列表对对象列表进行排序的 pythonic 方式是什么。

这是很有可能的,虽然很难看,使用 PostgreSQL 9.4+ 和 SQLAlchemy 0.9.7+。基本上我们构建一个 id -> ordinal 的映射,然后使用 JSONB -> 运算符找到每个用户 id 的序号(-> 需要 TEXT for JSON键

from sqlalchemy.sql.postgresql import JSONB, TEXT
from sqlalchemy.sql import cast

id_order = { str(v): k for k, v in enumerate(user_ids) }
users = User.query.filter(User.id.in_(user_ids)).\
    order_by(cast(id_order, JSONB)[cast(User.id, TEXT)])

这将创建类似于

的SQL ORDER BY
ORDER BY CAST('{"1": 2, "3": 0, "2": 1}' AS JSONB) ->
         CAST(user.id AS TEXT)

对于其他数据库,只需在客户端对其进行排序 - 虽然这意味着您无法浏览结果。

客户端排序的高效代码是:

id_order = { v: k for k, v in enumerate(user_ids) }
users = sorted(users, key=lambda u: id_order.get(u.id))