SQLALCHEMY忽略查询的重音

时间:2013-08-25 21:07:35

标签: python sqlalchemy flask diacritics

考虑到我的用户可以将数据保存为“café”或“cafe”,我需要能够使用不区分重音的查询搜索这些字段。

我找到了https://github.com/djcoin/django-unaccent/,但我不知道是否有可能在sqlalchemy上实现类似的东西。

我正在使用PostgreSQL,所以如果解决方案特定于这个数据库对我很好。如果它是通用解决方案,它会好得多。

感谢您的帮助。

2 个答案:

答案 0 :(得分:8)

一个简单且与数据库无关的解决方案是编写可以有两次重音的字段,一次有一次,一次没有重音。然后,您可以在非重音版本上进行搜索。

要生成字符串的非重音内容,您可以使用Unidecode

要在插入或更新记录时自动将非重音版本分配给数据库,您可以使用default定义中的onupdateColumn子句。例如,使用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

如果你有一个大表,请确保你有正确的索引,否则这将导致全表扫描。