代码之家  ›  专栏  ›  技术社区  ›  Yuval Adam

基于SQLAlchemy的Postgres不区分大小写索引

  •  1
  • Yuval Adam  · 技术社区  · 7 年前

    考虑一个带有索引的声明性SQLAlchemy模型 String

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

    这个 name 字段区分大小写,这意味着应该保留原始的大小写,但效率很高 不区分大小写 应支持对索引的查询。

    在SQLAlchemy中实现这一点的最佳方法是什么?

    查询可以使用 lower() 如果需要的话

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

    查询使用 ILIKE 下() 由于性能要求,它们是不可接受的,它们已经过测试,对于我的用例来说,在大型表上的执行速度不够快。

    1 回复  |  直到 7 年前
        1
  •  3
  •   Ilja Everilä    7 年前

    创建 functional index 对表达式进行索引 LOWER(name) :

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

    使用索引进行查询,例如

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

    可能表现更好,如果 下(名称)

    然后,您可以在 custom comparator :

    # 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'))