SQLALCHEMY忽略查询的重音

gui*_*nez 5 python sqlalchemy diacritics flask

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

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

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

谢谢你的帮助.

Mig*_*uel 8

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

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

要在插入或更新记录时自动将非重音版本分配给数据库,您可以使用定义中的defaultonupdate子句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)
Run Code Online (Sandbox Code Playgroud)

请注意我只是如何索引unaccented字段,因为这是进行搜索的字段.

当然,在您可以搜索之前,您还必须提取您正在搜索的值.例如:

def search(text):
    return MyModel.query.filter_by(some_string_unaccented = unaccent(text)).all()
Run Code Online (Sandbox Code Playgroud)

如有必要,您可以将相同的技术应用于全文搜索.


chl*_*nde 8

首先在PostgreSQL中安装unaccess扩展: create extension unaccent;

接下来,unaccent在Python中声明SQL函数:

from sqlalchemy.sql.functions import ReturnTypeFromArgs

class unaccent(ReturnTypeFromArgs):
    pass
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

for place in session.query(Place).filter(unaccent(Place.name) == "cafe").all():
    print place.name
Run Code Online (Sandbox Code Playgroud)

如果您有一个大表,请确保您具有正确的索引,否则将导致全表扫描.

  • 有效!我必须使用下面Miguel在搜索字符串上建议的unidecode.结果是这样的:`session.query(Place).filter((unaccent(Place.name).ilike(string)))`.它也忽略了案例.非常感谢! (2认同)