在SQLAlchemy中使用OR

Jim*_*ket 168 python sqlalchemy

我查看了文档,我似乎无法找到如何在SQLAlchemy中进行OR查询.我只是想做这个查询.

SELECT address FROM addressbook WHERE city='boston' AND (lastname='bulger' OR firstname='whitey')
Run Code Online (Sandbox Code Playgroud)

应该是这样的

addr = session.query(AddressBook).filter(City == "boston").filter(????)
Run Code Online (Sandbox Code Playgroud)

Thi*_*ter 294

SQLAlchemy的重载位运算符&,|~因此而不是与丑陋和难以阅读前缀语法or_()and_()(像巴斯蒂安的答案),你可以使用这些运营商:

.filter((AddressBook.lastname == 'bulger') | (AddressBook.firstname == 'whitey'))
Run Code Online (Sandbox Code Playgroud)

请注意,由于按位运算符的优先级,括号不是可选的.

所以你的整个查询看起来像这样:

addr = session.query(AddressBook) \
    .filter(AddressBook.city == "boston") \
    .filter((AddressBook.lastname == 'bulger') | (AddressBook.firstname == 'whitey'))
Run Code Online (Sandbox Code Playgroud)

  • @ChaseSandmann:是的,你可以.但它会更具可读性吗?没有. (20认同)
  • +1,但是你可以用更多的括号包含最后两个过滤器参数并在它们和第一个之间使用`&`(而不是使用第二个`filter`调用)来获得相同的效果吗? (8认同)

Bas*_*ard 290

教程:

from sqlalchemy import or_
filter(or_(User.name == 'ed', User.name == 'wendy'))
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这种方法支持使用生成器,所以如果你有很长的OR列表,你可以做`filter(或_(User.name == v for v in('Alice','Bob','Carl') ))` (69认同)
  • @ Robru的建议是不必要的低效率.如果你已经有了一个集合,那么你应该像这样使用`in_`运算符:`filter(User.name.in _(['Alice','Bob','Carl'])) (55认同)
  • @intgr如果你想使用另一个运算符而不是in_,例如LIKE运算符,那么robru显示的例子仍然有效. (7认同)
  • 啊,谢谢我不知道sqlalchemy有那个过滤器 (4认同)
  • @intgr我在Oracle上的经验表明,序列“ OR”比使用“ IN”要快得多。同样,“ IN”仅限于一组〜1000个条目,而“ OR”则不受限制。 (2认同)

Wil*_*oes 32

对于 SQLAlchemy ORM 2.0, 和|or_被接受。

文档

from sqlalchemy.future import select
from sqlalchemy.sql import or_


query = select(User).where(or_(User.name == 'ed', User.name == 'wendy'))
print(query)

# also possible:

query = select(User).where((User.name == 'ed') | (User.name == 'wendy'))
print(query)
Run Code Online (Sandbox Code Playgroud)


Val*_*lar 29

OR_运算符在OR查询组件数量未知的情况下非常有用.

例如,假设我们正在创建一个包含很少可选过滤器的REST服务,如果任何过滤器返回true,则应返回记录.另一方面,如果请求中未定义参数,则不应更改我们的查询.没有or_ function我们必须做这样的事情:

query = Book.query
if filter.title and filter.author:
    query = query.filter((Book.title.ilike(filter.title))|(Book.author.ilike(filter.author)))
else if filter.title:
    query = query.filter(Book.title.ilike(filter.title))
else if filter.author:
    query = query.filter(Book.author.ilike(filter.author))
Run Code Online (Sandbox Code Playgroud)

使用or_函数可以将其重写为:

query = Book.query
not_null_filters = []
if filter.title:
    not_null_filters.append(Book.title.ilike(filter.title))
if filter.author:
    not_null_filters.append(Book.author.ilike(filter.author))

if len(not_null_filters) > 0:
    query = query.filter(or_(*not_null_filters))
Run Code Online (Sandbox Code Playgroud)