Я реализую функцию поиска для имен пользователей. Некоторые имена имеют акцентированные символы, но я хочу, чтобы их можно было искать с ближайшим приближением ascii. Например: Vû Trån
будет доступен для поиска с Vu Tran
.Не удалось использовать ilike-метод SQLAlchemy с атрибутом getter
Я нашел библиотеку Python под названием unidecode
для обработки этого преобразования. Он работает как ожидалось и берет мою строку unicode Vû Trån
и возвращает Vu Tran
. Отлично.
Проблема возникает, когда я начинаю запрашивать мою базу данных - я использую SQLAlchemy и Postgres.
Вот мой Python запрос:
Person.query.filter(Person.ascii_name.ilike("%{q}%".format(q=query))).limit(25).all()
ascii_name
является геттером для моего колонка имени, реализованный в такой
class Person(Base, PersonUtil):
"""
My abbreviated Person class
"""
__tablename__ = 'person'
id = Column(BigInteger, ForeignKey('user.id'), primary_key=True)
first_name = Column(Unicode, nullable=False)
last_name = Column(Unicode, nullable=False)
name = column_property(first_name + " " + last_name)
ascii_name = synonym('name', descriptor=property(fget=PersonUtil._get_ascii_name))
class PersonUtil(object):
def _get_ascii_name(self):
return unidecode(unicode(self.name))
Моей целью этого кодом является то, что, так как я храню версию Юникода имя и фамилия в моей базе данных, мне нужно иметь способ позвонить unidecode(unicode(name))
, когда я получаю имя человека. Следовательно, я использую descriptor=property(fget=...)
, так что всякий раз, когда я вызываю Person.ascii_name
, я извлекаю атрибут «unidecoded» name
. Таким образом, я могу просто написать Person.ascii_name.ilike("%{my_query}%")...
и сопоставить ближайший ascii_name с поисковым запросом, который также является просто символом ascii.
Это не работает. Метод ilike
с ascii_name
работает, когда у меня нет преобразованных символов в запросе. Например, запрос ilike
будет работать для имени «Bob Smith», но он не будет работать для «Bøb Smíth». Он терпит неудачу, когда он сталкивается с первым преобразованным персонажем, который в случае с «Bøb Smíth» является буквой «ø».
Я не уверен, почему это происходит. Получатель ascii_name
возвращает ожидаемую строку «Bob Smith» или «Vu Tran», но в сочетании с методом ilike
он не работает.
- Почему это происходит? Я не смог найти ничего об этом.
- Как я могу исправить мой существующий код, чтобы сделать эту работу, или есть лучший способ сделать это, что будет работать? Я бы предпочел не менять схему БД.
спасибо.
В PostgreSQL есть нечто подобное: http://stackoverflow.com/questions/11005036/does-postgresql-support-accent-insensitive-collations – pozs