使用SQLAlchemy在Postgres中区分大小写的索引

尤瓦尔·亚当

考虑带有索引String字段的声明性SQLAlchemy模型

class User(Base):
    name = Column(String(100), index=True, nullable=False)

name字段区分大小写,这意味着应保留原始大小写,但应支持对索引进行有效的不区分大小写的查询。

实现此目标并在SQLAlchemy中实现的最佳方法是什么?

查询可以lower()根据需要使用

session.query(User).filter_by(name=lower('SOME_name'))

但是没关系,只要解决方案既优雅又高效。

由于性能要求,使用ILIKE和Postgres级的查询lower()是不可接受的,它们已经过测试,并且在我的用例中不能在大型表上执行得足够快。

IljaEverilä

创建一个索引表达式函数索引LOWER(name)

Index('idx_user_name_lower', func.lower(User.name))

有了索引后,查询如

session.query(User).filter(func.lower(User.name) == 'SOME_name'.lower())

如果LOWER(name)基数较高,可能会更好

然后,您可以在自定义比较器中封装处理小写字母的代码

# Verbatim from the documentation
class CaseInsensitiveComparator(Comparator):
    def __eq__(self, other):
        return func.lower(self.__clause_element__()) == func.lower(other)

class User(Base):
    ...
    @hybrid_property
    def name_insensitive(self):
        return self.name.lower()

    @name_insensitive.comparator
    def name_insensitive(cls):
        return CaseInsensitiveComparator(cls.name)

比较器将应用于func.lower()幕后双方:

session.query(User).filter_by(name_insensitive='SOME_name')

相当于

session.query(User).filter(func.lower(User.name) == func.lower('SOME_name'))

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章