【问题标题】:Order by query output column按查询输出列排序
【发布时间】:2020-11-24 16:25:54
【问题描述】:

我将石墨烯与 sqlalchemy 一起使用,并且我有一个包含计算字段的输出对象。该字段是根据一些输入(查询)参数计算的,或多或少看起来像这样(为了简化,让我们考虑我正在计算 f(x)=ax+b 其中 a 和 b 都是我的列 Thing表):

import models

class Thing(SQLAlchemyObjectType):
    class Meta:
        model = models.Thing
        interfaces = (relay.Node, )

    f = graphene.Field(graphene.Float)

    def resolve_f(self, info):
        return self.a * info.context['x'] + self.b

在我的查询中,我有以下内容,我想根据函数f 的输出对字段进行排序:

class Query(graphene.ObjectType):
    best_points = graphene.List(lambda: Thing, x = graphene.Float())

    def resolve_best_points(self, info, x):
        query = Thing.get_query(info)
        return query.all()

起初我尝试在resolve_best_points 中使用query.order_by("f").all() 之类的东西进行排序,但由于石墨烯似乎在解析器之外添加了这个字段(即query.all() 仅包含ab 但不是f(a, b))。

有没有办法以干净的方式实现这一目标?在Thing 中添加一些选项?或者也许在解析器中获取输出值然后排序?或者像添加一个中间件来对来自resolve_best_points 的输出进行排序这样更难看的东西?

什么是可能的,对此可能的解决方案有什么优点/缺点?

请注意,这与以下问题有些相关:Sqlalchemy order by calculated column,但这也完全不同,因为在这里我不希望仅基于数据库字段进行计算(当前解决方案在涉及变量时不起作用,例如info.context['x'] 在这个玩具示例中)。

【问题讨论】:

  • 这也是我的问题。问题是我们无法从顶层访问在较低级别生成的数据。

标签: sqlalchemy graphene-python graphene-sqlalchemy


【解决方案1】:

您可以使用 SQLAlchemy 的 orm.with_expressionorm.query_expression 函数将即席表达式应用于您的查询,然后在 ORDER_BY 子句中使用它们。

query_expression 属性添加到您的Thing 模型。

# models.py
from sqlalchemy import Float, Integer, orm

class Thing(Base):
    __tablename__ = 'things'
    id = Column(Integer, primary_key=True)
    a = Column(Float)
    b = Column(Float)

    expr = orm.query_expression()

您现在可以使用with_expression 将任意 SQL 表达式传递给您的查询。 Thing 对象上的expr 属性的值将是表达式的结果。

# schema.py
import graphene

from graphene import relay
from sqlalchemy.orm import with_expression

from models import Thing as ThingModel


class Thing(SQLAlchemyObjectType):
    class Meta:
        model = ThingModel
        interfaces = (relay.Node,)


class Query(graphene.ObjectType)
    best_points = graphene.List(Thing, x=graphene.Float())

    def resolve_best_points(self, info, x):
        expr = ThingModel.a * x + ThingModel.b

        return (
            Thing.get_query(info)
            .options(with_expression(ThingModel.expr, expr))
            .order_by(expr)
            .all()
        )

更多细节和需要注意的注意事项列表在 SQLAlchemy 文档的这一部分:Query-time SQL expressions as mapped attributes

【讨论】:

    猜你喜欢
    • 2023-04-03
    • 2012-07-30
    • 2014-08-09
    • 1970-01-01
    • 1970-01-01
    • 2021-08-13
    • 1970-01-01
    • 2010-11-01
    • 2021-10-13
    相关资源
    最近更新 更多