我正在为用户名实现搜索功能。有些名称有重音字符,但我希望能够用最近的ascii字符近似值搜索它们。例如:Vû Trån
可以使用Vu Tran
进行搜索。
我找到了一个名为unidecode
的Python库来处理这种转换。它按预期工作,并获取我的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))
我在这段代码背后的意图是,因为我在我的数据库中存储了名字和名字的unicode版本,所以当我检索这个人的名字时,我需要有办法调用unidecode(unicode(name))
。因此,我使用descriptor=property(fget=...)
,这样每当我调用Person.ascii_name
时,我都会检索“未编码的”name
属性。这样,我只需编写Person.ascii_name.ilike("%{my_query}%")...
并将最近的ascii_name与搜索查询匹配,搜索查询也只是ascii字符。
这不完全有效。如果查询中没有任何转换后的字符,ilike
ascii_name
方法可以正常工作。例如,ilike
查询将用于名称“Bob Smith”,但它不适用于“BøbSmíth”。遇到第一个转换后的角色失败,在“BøbSmíth”的情况下是“ø”字母。
我不确定为什么会这样。 ascii_name
getter返回我期望的“Bob Smith”或“Vu Tran”字符串,但当与ilike
方法结合使用时,它不起作用。
谢谢。
答案 0 :(得分:0)
您想要做的事情根本不起作用,因为ilike
仅适用于数据库中的真实列。 column_property
和synonym
只是sqlalchemy提供的语法糖,有助于简化前端。如果您想利用后端以您想要的方式使用LIKE
进行查询,则需要实际值。我恐怕你必须在数据库中生成/存储ascii全名,这意味着你需要更改你的模式以包含ascii_name作为一个真正的列,并确保它们被插入。要自己验证,您应该转储表中的数据,看看手动构建的查询是否可以正常工作。