按查询输出列排序
Order by query output column
我将石墨烯与 sqlalchemy 结合使用,并且我有一个包含计算字段的输出对象。该字段是根据一些输入(查询)参数计算的,或多或少看起来像这样(为了简化,让我们考虑我正在计算 f(x)=ax+b 其中 a 和 b 都是我的列
Thing
table):
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()
起初我尝试使用 query.order_by("f").all()
之类的方法在 resolve_best_points
内进行排序,但没有成功,因为石墨烯似乎将此字段添加到解析器之外(即 query.all()
仅包含a
和 b
但不是 f(a, b)
).
有没有办法以干净的方式实现这一目标?在 Thing
中添加一些选项?或者也许在解析器中获取输出值然后排序?或者有点丑陋的东西,比如添加一个中间件来对 resolve_best_points
?
的输出进行排序
什么是可能的,pros/cons 可能的解决方案是什么?
请注意,这与这个问题有些相关:Sqlalchemy order by calculated column,但这也有很大的不同,因为在这里我不希望仅基于数据库字段进行计算(当前的解决方案在有涉及的变量,例如这个玩具示例中的 info.context['x']
)。
您可以使用 SQLAlchemy 的 orm.with_expression
和 orm.query_expression
函数将 ad-hoc 表达式应用于您的查询,然后在 ORDER_BY
子句中使用它们。
为您的 Thing
模型添加 query_expression
属性。
# 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.
我将石墨烯与 sqlalchemy 结合使用,并且我有一个包含计算字段的输出对象。该字段是根据一些输入(查询)参数计算的,或多或少看起来像这样(为了简化,让我们考虑我正在计算 f(x)=ax+b 其中 a 和 b 都是我的列
Thing
table):
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()
起初我尝试使用 query.order_by("f").all()
之类的方法在 resolve_best_points
内进行排序,但没有成功,因为石墨烯似乎将此字段添加到解析器之外(即 query.all()
仅包含a
和 b
但不是 f(a, b)
).
有没有办法以干净的方式实现这一目标?在 Thing
中添加一些选项?或者也许在解析器中获取输出值然后排序?或者有点丑陋的东西,比如添加一个中间件来对 resolve_best_points
?
什么是可能的,pros/cons 可能的解决方案是什么?
请注意,这与这个问题有些相关:Sqlalchemy order by calculated column,但这也有很大的不同,因为在这里我不希望仅基于数据库字段进行计算(当前的解决方案在有涉及的变量,例如这个玩具示例中的 info.context['x']
)。
您可以使用 SQLAlchemy 的 orm.with_expression
和 orm.query_expression
函数将 ad-hoc 表达式应用于您的查询,然后在 ORDER_BY
子句中使用它们。
为您的 Thing
模型添加 query_expression
属性。
# 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.