postgresql 如何在django中进行不敏感的TrigramSimilarity搜索?

omvjsjqw  于 2023-04-29  发布在  PostgreSQL
关注(0)|答案(2)|浏览(197)

如何在django文档中添加不区分重音的搜索:

>>> from django.contrib.postgres.search import TrigramSimilarity
>>> Author.objects.create(name='Katy Stevens')
>>> Author.objects.create(name='Stephen Keats')
>>> test = 'Katie Stephens'
>>> Author.objects.annotate(
...     similarity=TrigramSimilarity('name', test),
... ).filter(similarity__gt=0.3).order_by('-similarity')
[<Author: Katy Stevens>, <Author: Stephen Keats>]

这怎么可能匹配test = 'Kâtié Stéphèns'

wbgh16ku

wbgh16ku1#

存在非重音查找:
非重音查找允许您使用专用的PostgreSQL扩展执行重音不敏感的查找。
另外,如果你看一下django文档的聚合部分,你可以阅读以下内容:
当在聚合函数中指定要聚合的字段时,**Django将允许您使用与在过滤器中引用相关字段时相同的双下划线表示法。**Django将处理任何需要检索和聚合相关值的表连接。

来源于以上:

您可以使用trigram_similar查找,结合unaccent,然后在结果上使用annotate

Author.objects.filter(
    name__unaccent__trigram_similar=test
).annotate(
    similarity=TrigramSimilarity('name__unaccent', test),
).filter(similarity__gt=0.3).order_by('-similarity')
  • 或 *

如果你想让它尽可能接近原始样本(并省略一个可能慢的过滤,然后是另一个):

Author.objects.annotate(
    similarity=TrigramSimilarity('name__unaccent', test),
).filter(similarity__gt=0.3).order_by('-similarity')

这些只适用于Django版本〉= 1。10
编辑:

虽然上面的操作应该可以工作,但@Private报告发生了此错误:

Cannot resolve keyword 'unaccent' into a field. Join on 'unaccented' not permitted.

这可能是一个bug,或者unaccent不打算以这种方式工作。下面的代码可以正常工作,没有错误:

Author.objects.filter(
    name__unaccent__trigram_similar=test
).annotate(
    similarity=TrigramSimilarity('name', test),
).filter(similarity__gt=0.3).order_by('-similarity')
nwo49xxi

nwo49xxi2#

如果它对某人有用,上面的解决方案对我不起作用。
我不得不这么做:

from django.db.models import Transform
from django.contrib.postgres.search import TrigramSimilarity

class Unaccent2(Transform):
   function = "UNACCENT"
   lookup_name = "unaccent"

def remove_accents(input_str):
   nfkd_form = unicodedata.normalize('NFKD', input_str)
   only_ascii = nfkd_form.encode('ASCII', 'ignore')
   return only_ascii.decode()

qs = Author.objects.annotate(similarity=TrigramSimilarity(Unaccent2('name'), remove_accents(q))
qs = qs.filter(similarity__gt=0.3).order_by('-similarity')

相关问题