sqlalchemy 过滤多列

Posted

技术标签:

【中文标题】sqlalchemy 过滤多列【英文标题】:sqlalchemy filter multiple columns 【发布时间】:2011-03-20 23:11:02 【问题描述】:

如何合并两列并应用过滤器?例如,我想同时在“firstname”和“lastname”列中进行搜索。如果只搜索一列,这就是我的做法:

query = meta.Session.query(User).filter(User.firstname.like(searchVar))

【问题讨论】:

我认为这个问题与我遇到的问题相匹配,但答案不适用于我的特定场景。如果名字是“joe”并且姓氏是“smith”,我正在寻找一个过滤器语句,当提供的 searchVar 是“joe smith”时匹配。即,在进行测试之前,需要连接字段(添加空格)。似乎是一个非常真实的场景。 @Groovee60 这正是我想要的。如果您能分享您的解决方案,如果您找到了,我将不胜感激。 【参考方案1】:

有很多方法可以做到:

使用filter()and 运算符)

query = meta.Session.query(User).filter(
    User.firstname.like(search_var1),
    User.lastname.like(search_var2)
    )

使用filter_by()and 运算符)

query = meta.Session.query(User).filter_by(
    firstname.like(search_var1),
    lastname.like(search_var2)
    )

链接filter()filter_by()and 运算符)

query = meta.Session.query(User).\
    filter_by(firstname.like(search_var1)).\
    filter_by(lastname.like(search_var2))

使用or_()and_()not()

from sqlalchemy import and_, or_, not_

query = meta.Session.query(User).filter(
    and_(
        User.firstname.like(search_var1),
        User.lastname.like(search_var2)
    )
)

【讨论】:

这些不同的方法是否有任何值得注意的性能差异? 大多数不同的方法最终都会生成相同的查询,因此在大多数情况下您不会看到性能差异。 我有点困惑。用于按关键字参数过滤的filter_by docs say:query(Foo).filter_by(bar='baz')。这与您在上面的答案中使用的语法有什么关系? filter_by 只接受一个参数【参考方案2】:

您可以简单地调用filter 多次:

query = meta.Session.query(User).filter(User.firstname.like(searchVar1)). \
                                 filter(User.lastname.like(searchVar2))

【讨论】:

在大型 mysql 表上使用多个filter() 方法和在单个filter 中使用多个条件的组合(通过or_and_)之间是否存在性能差异? 多个filter 调用会像逻辑AND 而不是OR 吗? 我不这么认为——当您查看 str(User.filter(cond1).filter(cond2)) 时,只使用“and”ed 条件生成最终的 sql。【参考方案3】:

您可以使用 SQLAlchemy 的 or_ function 在多个列中进行搜索(需要下划线以将其与 Python 自己的 or 区分开来)。

这是一个例子:

from sqlalchemy import or_
query = meta.Session.query(User).filter(or_(User.firstname.like(searchVar),
                                            User.lastname.like(searchVar)))

【讨论】:

您可以使用| 运算符而不是or_,就像这样-(User.firstname.like(searchVar)) | (User.lastname.like(searchVar)),但是您应该小心| 的优先级,如果没有括号,当与比较运算符。 不应该是filter.or_( case1, case 2)吗? 这是错误的,因为问题是关于 ORM 但链接会导致表达式。 我使用了多个过滤器语句,在此之前显着增加了延迟。我将其更改为 or_ 并且它的返回速度要快得多。谢谢@gclj5【参考方案4】:

适用于多列的通用代码。 如果需要在应用程序中有条件地实现搜索功能,也可以使用它。

search_key = "abc"
search_args = [col.ilike('%%%s%%' % search_key) for col in ['col1', 'col2', 'col3']]
query = Query(table).filter(or_(*search_args))
session.execute(query).fetchall()

注意:%% 对于跳过 % 格式化查询很重要。

【讨论】:

以上是关于sqlalchemy 过滤多列的主要内容,如果未能解决你的问题,请参考以下文章

使用 sqlalchemy 的声明性 ORM 扩展时的多列索引

使用 sqlalchemy 查询使用多列 where in 子句

如何在sqlalchemy中选择多列连接的特定列?

SQLAlchemy:如何过滤日期字段?

SqlAlchemy - 按关系属性过滤

SQLAlchemy - 过滤子查询负载