考虑到我的用户可以将数据保存为“café”或“cafe”,我需要能够使用不区分重音的查询在该字段上进行搜索。
我找到了https://github.com/djcoin/django-unaccent/,但我不知道是否可以在 sqlalchemy 上实现类似的东西。
我正在使用 PostgreSQL,所以如果解决方案是特定于这个数据库的,对我有好处。如果是通用解决方案,那就更好了。
谢谢你的帮助。
考虑到我的用户可以将数据保存为“café”或“cafe”,我需要能够使用不区分重音的查询在该字段上进行搜索。
我找到了https://github.com/djcoin/django-unaccent/,但我不知道是否可以在 sqlalchemy 上实现类似的东西。
我正在使用 PostgreSQL,所以如果解决方案是特定于这个数据库的,对我有好处。如果是通用解决方案,那就更好了。
谢谢你的帮助。
首先在 PostgreSQL 中安装 unaccess 扩展:create extension unaccent;
接下来,unaccent
在 Python 中声明 SQL 函数:
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
如果您有一个大表,请确保您有正确的索引,否则这将导致全表扫描。
一个简单且与数据库无关的解决方案是编写可以有两次重音的字段,一次有重音,一次没有重音。然后,您可以对非重音版本进行搜索。
要生成字符串的非重音版本,您可以使用Unidecode。
要在插入或更新记录时自动将非重音版本分配给数据库,您可以在定义中使用default
andonupdate
子句。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()
如有必要,您可以将相同的技术应用于全文搜索。