[英]Order by query output column
I'm using graphene with sqlalchemy and I have an output object that contains a computed field.我正在使用带有 sqlalchemy 的石墨烯,并且我有一个包含计算字段的 output object。 The field is computed according to some input (query) parameter and more or less look like this (to simplify, lets consider I'm computing f(x)=ax+b where a and b are both columns in my
Thing
table):该字段是根据一些输入(查询)参数计算的,或多或少看起来像这样(为了简化,让我们考虑我正在计算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
In my query I have the following and I would like to sort fields according to the output of the function f
:在我的查询中,我有以下内容,我想根据 function
f
的 output 对字段进行排序:
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()
At first I've tried sorting within resolve_best_points
using something like query.order_by("f").all()
but in vain since graphene seems to add this field outside the resolver (ie., query.all()
only contains a
and b
but not f(a, b)
).起初,我尝试使用类似
query.order_by("f").all()
在resolve_best_points
中进行排序,但由于石墨烯似乎将此字段添加到解析器之外(即query.all()
仅包含a
和b
但不是f(a, b)
)。
Is there a way to achieve this in a clean way?有没有办法以干净的方式实现这一目标? Adding some option in
Thing
?在
Thing
中添加一些选项? Or maybe obtaining the output values within the resolver and then sorting?或者也许在解析器中获取 output 值然后排序? Or something a bit uglier like adding a middleware to sort outputs from
resolve_best_points
?或者更难看的东西,比如添加一个中间件来对
resolve_best_points
的输出进行排序?
What is possible, what are the pros/cons of possible solutions to this?什么是可能的,可能的解决方案的优点/缺点是什么?
Note that this is somewhat related to this question: Sqlalchemy order by calculated column , but this is also quite different because here I don't want a calculation based on database fields only (current solutions do not work when there are variables involved, like info.context['x']
in this toy example).请注意,这与这个问题有些相关: Sqlalchemy order by computed column ,但这也有很大不同,因为这里我不希望仅基于数据库字段进行计算(当前解决方案在涉及变量时不起作用,例如
info.context['x']
在这个玩具示例中)。
You can use SQLAlchemy's orm.with_expression
and orm.query_expression
functions to apply ad-hoc expressions to your query, then use them in the ORDER_BY
clause.您可以使用 SQLAlchemy 的
orm.with_expression
和orm.query_expression
函数将临时表达式应用于您的查询,然后在ORDER_BY
子句中使用它们。
Add a query_expression
attribute to your Thing
model.将
query_expression
属性添加到您的Thing
model。
# 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()
You can now use with_expression
to pass arbitrary SQL expressions to your queries.您现在可以使用
with_expression
将任意 SQL 表达式传递给您的查询。 The value of the expr
attribute, on Thing
objects, will be the result of the expression. 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()
)
More details and a list of caveats to be aware of are in this section of the SQLAlchemy docs: Query-time SQL expressions as mapped attributes . SQLAlchemy 文档的此部分中提供了更多详细信息和需要注意的注意事项列表: 查询时 SQL 表达式作为映射属性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.