Индексирование без учета регистра в Postgres с помощью SQLAlchemy - PullRequest
0 голосов
/ 30 октября 2018

Рассмотрим декларативную модель 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 и уровня Postgres lower() неприемлемы из-за требований к производительности, они были протестированы и не выполняют достаточно быстро на больших таблицах для моего варианта использования.

1 Ответ

0 голосов
/ 30 октября 2018

Создать функциональный индекс , который индексирует выражение 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'))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...