Перейти к содержанию

PostgreSQL: сходство по триграммам и unaccent

Поиск текста по сходству через расширение pg_trgm и сравнение без диакритических знаков через unaccent. Объявите расширения в Meta.extensions (("pg_trgm", "unaccent")), и автоматическое создание миграций их создаст:

from hare.dialects.postgresql.functions import TrigramSimilarity

await Author.objects.filter(name__trigram_similar="Gerard Depardeu")
await Author.objects.filter(name__unaccent__icontains="saldana")
await Author.objects.annotate(score=TrigramSimilarity("name", "Gerard")).filter(score__gt=0.3).order_by("-score")

Операторы фильтра

Оператор фильтра Оператор SQL Подходят строки, где
trigram_similar % текст похож на значение (pg_trgm.similarity_threshold)
trigram_word_similar %> значение похоже на часть текста (pg_trgm.word_similarity_threshold)
trigram_strict_word_similar %>> значение похоже на целые слова текста

unaccent

unaccent — часть пути у CharField/TextField/CitextField: name__unaccent — текст без диакритических знаков (unaccent()), после которого идут текстовые операторы (name__unaccent__icontains, name__unaccent__trigram_similar); работает также в values(), order_by() и F().

Оценки сходства

В hare.dialects.postgresql.functions есть оценки сходства — числа с плавающей точкой от 0 до 1:

Функция SQL
TrigramSimilarity(expression, string) similarity(expression, string)
TrigramDistance(expression, string) expression <-> string
TrigramWordSimilarity(string, expression) word_similarity(string, expression)
TrigramWordDistance(string, expression) string <<-> expression
TrigramStrictWordSimilarity(string, expression) strict_word_similarity(string, expression)
TrigramStrictWordDistance(string, expression) string <<<-> expression