【问题标题】:SQLAlchemy: How to output a calculated field that takes in parameters from the user as inputSQLAlchemy:如何输出一个计算字段,该字段接受用户的参数作为输入
【发布时间】:2022-10-06 09:13:07
【问题描述】:

我有一个这样的模型:

class User:
    __tablename__ = \"user\"

    first_name = Column(String(), nullable=False)
    last_name = Column(String(), nullable=False)

然后我有一个这样的查询:

name = [\"...\", ...]
user_query = (
    db.session.query(User)
    .add_column(case([
        (and_(User.first_name).ilike(f\'%{name}%\'), User.last_name.ilike(f\'%{name}%\')), True),
        (or_(User.first_name).ilike(f\'%{name}%\'), User.last_name.ilike(f\'%{name}%\')), False)
    ]).label(\'perfect_match\'))
    .order_by(literal_column(\"\'perfect_match\"))
)

这显然是一种过度简化,但基本上我正在尝试跨字段进行搜索并将完美匹配与不完美匹配分开排序。

这给了我一个错误,说“完美匹配”列不存在,所以我认为我在这里错误地使用了add_column

我也尝试像这样使用hybrid_method

@hybrid_method
def perfect_match(self, terms):
    perfect_match = True
    matched = False
    for term in terms:
        if term.lower() in self.first_name.lower() or term.lower() in self.last_name.lower():
            matched = True
            continue
        perfect_match = False

    return perfect_match if matched else None

@perfect_match.expression
def perfect_match(self, terms):
    perfect_match = and_(...)
    imperfect_match = or_(...)

    return case(...)

然后我的查询如下所示:

name = [...]
user_query = (
    db.session.query(User)
    .filter(User.perfect_match(name) != None)
    .order_by(User.perfect_match(name))

我希望perfect_match 在输出中。这是我想要的 SQL:

SELECT
    first_name,
    last_name,
    case (
        ...
    ) as perfect_match
FROM user
WHERE perfect_match != NULL
ORDER BY perfect_match

第一次使用add_column 给了我那个SQL,但是SQLAlchemy 错误说它不能列perfect_match 不存在。第二个(使用hybrid_method)将 case 放在 WHERE 和 ORDER BY 子句中(可能效率低下?)并且在输出中不包括 perfect_match,但它似乎工作正常。我需要使用该输出列来确定完美匹配的结束位置。

我试过了:

  • 将完美匹配添加为列(布尔值)
  • 将完美匹配添加为 column_property()
  • 将 perfect_match 添加为 .query(User, literal_column(\"\'perfect_match\"))

有什么想法吗?我见过的大多数例子都使用hybrid_property,但我需要在这里提出一个论点。我对 SQLAlchemy 很陌生,所以我可能错过了一些东西。

    标签: python postgresql sqlalchemy


    【解决方案1】:

    有一个类似的问题,需要一个基于仅在运行时可用的参数的虚拟/属性,只是一个布尔值。

    我试过这个SQLAlchemy hybrid method as an attribute in the query result? 并没有用,我希望从模型到模式的转换更直接,所以我这样做了。

    定义一个名为完美的一对在您的模型中作为query_expression()

    class User(BaseModel):
        ...
        perfect_match = query_expression()
        ...
    

    然后在构建查询或语句时,根据您的情况定义一个表达式:

    exp = case([
        (and_(User.first_name).ilike(f'%{name}%'), User.last_name.ilike(f'%{name}%')), True),
        (or_(User.first_name).ilike(f'%{name}%'), User.last_name.ilike(f'%{name}%')), False)])
    query = (
        db.session.query(User)
        .options(with_expression(User.perfect_match, exp))
        .filter(User.perfect_match(name) != None)
        .order_by(User.perfect_match(name)
    )
    return query.all()
    

    它也可以使用语句,语法相同。 Pydantic 应该将该领域视为柱子.

    【讨论】:

      猜你喜欢
      • 2014-05-13
      • 1970-01-01
      • 1970-01-01
      • 2021-09-05
      • 2021-10-25
      • 1970-01-01
      • 2017-05-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多