【问题标题】:How can I order by a custom function in SQLAlchemy如何通过 SQLAlchemy 中的自定义函数进行排序
【发布时间】:2018-12-09 19:33:20
【问题描述】:

所以我有一个如下所示的 SQLALchemy 模型

from sqlalchemy import (create_engine, Column, BigInteger, String, 
                        DateTime)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property

Base = declarative_base()

class Trades(Base):

    __tablename__ = 'trades'

    row_id = Column(BigInteger, primary_key=True, autoincrement=True)
    order_id = Column(String)
    time = Column(DateTime)
    event_type = Column(String)

    @hybrid_property
    def event_type_to_integer(self):
        return dict(received=0, open=1, done=2)[self.event_type]

    @event_type_to_integer.expression
    def event_type_to_integer(self):
        pass

我希望能够先通过time 然后通过event_type 订购查询。按时间排序很容易,因为日期时间具有自然排序。但是按event_type 排序有点棘手,因为event_type 可以取值receivedopendone。我希望我的所有查询都按上述指定顺序按event_type 排序查询。看来我需要使用我在上面开始做的混合属性,但是要让order_by 函数工作,似乎我还需要编写

    @event_type_to_integer.expression
    def event_type_to_integer(self):
        pass

功能。这是我画一个空白的地方。有没有人有关于如何编写这个函数来完成上述操作的建议。我试过阅读文档和类似的 StackOverflow 帖子。还是有问题。以供参考。这是我正在尝试的查询

    sess = Session()

    orders = (
        sess
        .query(Trades)
        .order_by(Trades.time.asc(), Trades.event_type_to_integer.asc())
        .all()
        )

    sess.close()

它正在抛出一个

KeyError: <sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x7fcb11861048>

【问题讨论】:

  • 也许我理解错了,但你不能只按你的event_type 列按降序排序,因为你希望这些值按字母倒序排列吗?换句话说,session.query(Trades).order_by(Trades.time.asc(), Trades.event_type.desc()).all() 对你不起作用有什么原因吗?
  • @benvc 是的,我想这是一个解决方案。我将其描述为有点 hacky,因为它利用的是巧合的属性,而不是代表数据的底层逻辑。我希望找到更强大的东西。

标签: python postgresql sqlalchemy


【解决方案1】:

您可以在 SQL 中使用 CASE expression 实现查找:

from sqlalchemy import case

_event_type_lookup = dict(received=0, open=1, done=2)

class Trades(Base):
    ...
    @hybrid_property
    def event_type_to_integer(self):
        return _event_type_lookup[self.event_type]

    @event_type_to_integer.expression
    def event_type_to_integer(cls):
        return case(_event_type_lookup, value=cls.event_type)

这使用case() 构造的value 简写来生成一个表达式,该表达式将给定的列表达式与字典中传递的键进行比较,生成映射值作为结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多