考虑到我的用户可以将数据保存为“café”或“cafe”,我需要能够使用不区分重音的查询搜索这些字段。
我找到了https://github.com/djcoin/django-unaccent/,但我不知道是否有可能在sqlalchemy上实现类似的东西。
我正在使用PostgreSQL,所以如果解决方案特定于这个数据库对我很好。如果它是通用解决方案,它会好得多。
感谢您的帮助。
答案 0 :(得分:8)
一个简单且与数据库无关的解决方案是编写可以有两次重音的字段,一次有一次,一次没有重音。然后,您可以在非重音版本上进行搜索。
要生成字符串的非重音内容,您可以使用Unidecode。
要在插入或更新记录时自动将非重音版本分配给数据库,您可以使用default
定义中的onupdate
和Column
子句。例如,使用Flask-SQLAlchemy,您可以执行以下操作:
from unidecode import unidecode
def unaccent(context):
return unidecode(context.current_parameters['some_string'])
class MyModel(db.Model):
id = Column(db.Integer, primary_key=True)
some_string = db.Column(db.String(128))
some_string_unaccented = db.Column(db.String(128), default=unaccent, onupdate=unaccent, index=True)
请注意我是如何仅对非重音字段编制索引的,因为这是进行搜索的字段。
当然,在您可以搜索之前,您还必须提取您正在搜索的值。例如:
def search(text):
return MyModel.query.filter_by(some_string_unaccented = unaccent(text)).all()
如有必要,您可以将相同的技术应用于全文搜索。
答案 1 :(得分:8)
首先在PostgreSQL中安装unaccess扩展:create extension unaccent;
接下来,在Python中声明SQL函数unaccent
:
from sqlalchemy.sql.functions import ReturnTypeFromArgs
class unaccent(ReturnTypeFromArgs):
pass
并像这样使用它:
for place in session.query(Place).filter(unaccent(Place.name) == "cafe").all():
print place.name
如果你有一个大表,请确保你有正确的索引,否则这将导致全表扫描。