SqlAlchemy的Python等价于'startswith'

9

我有一个字符串,需要查找所有具有匹配前缀的记录:

path = '/abc/123/456'
session.query(Site).filter(path.startswith(Site.path_prefix))

以下记录将在path_prefix等于以下内容时匹配:
/abc
/ab
/abc/123

但不包括:

/asd
/abc/123/456/789
/kjk

使用SqlAlchemy,而不需要切换到Python,这是否可能?


你是指 Site.path_prefix in path 吗?此外,在纯 Python 语义中,这将匹配像 23/4 和空字符串一样的字符串,这是你想要的吗? - kennytm
@KennyTM,感谢您的纠正。我只需要前缀。 - TheOne
1个回答

15

如果你将path变量包装在一个bindparam()对象中,那么你可以像对待任何列一样对待它,包括使用.contains().startswith()运算符:

from sqlalchemy.sql.expression import bindparam

session.query(Site).filter(bindparam('path', path).contains(Site.path_prefix))

SQLAlchemy将.contains()翻译为:

? LIKE CONCAT('%', Site.path_prefix, '%')

关于 MySQL 或者

? LIKE '%' || Site.path_prefix || '%'

在其他数据库上也可以进行测试。

如果您想要测试 .startswith() 操作,那也可以:

from sqlalchemy.sql.expression import bindparam

session.query(Site).filter(bindparam('path', path).startswith(Site.path_prefix))

我在想 startswith (path,Site.path_prefix)(将 path_prefix,path 作为参数)难道不正是我们陷入的陷阱吗? - Jon Clements
@JonClements:当然,但这与“in”不同。我已经添加了选项;只需删除第一个“%”通配符即可。SQLAlchemy确实提供了一个startswith(),但仅适用于列,因为这是反向的,所以我们需要自己构建LIKE - Martijn Pieters
@MartijnPieters,有没有与sqlite可用的concat替代方案?似乎在那里不支持concat:OperationalError: (OperationalError) no such function: concat u'SELECT... - TheOne
@Ramin:啊,我的错误,functions.concat() 是过度的。使用 + 字符串连接就足够了,它会正确地转换为不同的数据库。 - Martijn Pieters
@Ramin:实际上,由于中心前提是使用 bindparam(),因此 SQLAlchemy 的 .startswith().contains() 运算符也可以使用。 - Martijn Pieters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接