Search extras (Headline, weighted rank, trigram distance/word)

Django ORM PostgreSQL May 22, 2026 python

Beyond basic search: SearchHeadline returns a snippet with matches wrapped in markers; weighting a SearchVector (A > B > C > D) influences SearchRank; TrigramDistance is 1 − similarity (order ascending for closest); and TrigramWordSimilarity matches a wor

python
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
# ======================================================================
# Beyond basic search: `SearchHeadline` returns a snippet with matches wrapped
# in markers; weighting a `SearchVector` (A > B > C > D) influences
# `SearchRank`; `TrigramDistance` is `1 − similarity` (order ascending for
# closest); and `TrigramWordSimilarity` matches a word *inside* a longer string.
# ======================================================================

# ----------------------------------------------------------------------
# SearchHeadline wraps matches in [ ]
# ----------------------------------------------------------------------

# Django:
query = SearchQuery("rings", search_type="websearch")
Book.objects.annotate(
    headline=SearchHeadline("title", query, start_sel="[", stop_sel="]")
).values_list("title", "headline")

# SQL:
#   SELECT "examples_book"."title" AS "title", ts_headline("examples_book"."title", websearch_to_tsquery('rings'), 'StartSel=''['', StopSel='']''') AS "headline"
#   FROM "examples_book"

# Result:
#   Harry Potter: Harry Potter
#   The Hobbit: The Hobbit
#   The Lord of the Rings: The Lord of the [Rings]
#   Postgres for Authors: Postgres for Authors

# ----------------------------------------------------------------------
# weighted SearchVector (A) + SearchRank
# ----------------------------------------------------------------------

# Django:
vector = SearchVector("title", weight="A")
query = SearchQuery("postgres")
Book.objects.annotate(rank=SearchRank(vector, query)) \
    .filter(rank__gt=0).order_by("-rank").values_list("title", "rank")

# SQL:
#   SELECT "examples_book"."title" AS "title", ts_rank(setweight(to_tsvector(COALESCE("examples_book"."title", '')), 'A'), plainto_tsquery('postgres')) AS "rank"
#   FROM "examples_book"
#   WHERE ts_rank(setweight(to_tsvector(COALESCE("examples_book"."title", '')), 'A'), plainto_tsquery('postgres')) > 0.0
#   ORDER BY 2 DESC

# Result:
#   Postgres for Authors: 0.6079

# ----------------------------------------------------------------------
# TrigramDistance (ascending = closest match)
# ----------------------------------------------------------------------

# Django:
Book.objects.annotate(dist=TrigramDistance("title", "potter")) \
    .order_by("dist").values_list("title", "dist")[:3]

# SQL:
#   SELECT "examples_book"."title" AS "title", ("examples_book"."title" <-> 'potter') AS "dist"
#   FROM "examples_book"
#   ORDER BY 2 ASC
#   LIMIT 3

# Result:
#   Harry Potter: 0.462
#   Postgres for Authors: 0.923
#   The Hobbit: 1.000

# ----------------------------------------------------------------------
# TrigramWordSimilarity ('lord' as a word inside the title)
# ----------------------------------------------------------------------

# Django:
Book.objects.annotate(sim=TrigramWordSimilarity("lord", "title")) \
    .order_by("-sim").values_list("title", "sim")[:3]

# SQL:
#   SELECT "examples_book"."title" AS "title", WORD_SIMILARITY('lord', "examples_book"."title") AS "sim"
#   FROM "examples_book"
#   ORDER BY 2 DESC
#   LIMIT 3

# Result:
#   The Lord of the Rings: 1.000
#   Harry Potter: 0.000
#   The Hobbit: 0.000

# ----------------------------------------------------------------------
# TrigramWordDistance + Strict word similarity/distance
# ----------------------------------------------------------------------

# Django:
Book.objects.annotate(
    wd=TrigramWordDistance("lord", "title"),
    ss=TrigramStrictWordSimilarity("lord", "title"),
    sd2=TrigramStrictWordDistance("lord", "title"),
).order_by("wd").values_list("title", "wd", "ss", "sd2")[:3]

# SQL:
#   SELECT "examples_book"."title" AS "title", ('lord' <<-> "examples_book"."title") AS "wd", STRICT_WORD_SIMILARITY('lord', "examples_book"."title") AS "ss", ('lord' <<<-> "examples_book"."title") AS "sd2"
#   FROM "examples_book"
#   ORDER BY 2 ASC
#   LIMIT 3

# Result:
#   The Lord of the Rings: word_dist=0.000 strict_sim=1.000 strict_dist=0.000
#   Harry Potter: word_dist=1.000 strict_sim=0.000 strict_dist=1.000
#   The Hobbit: word_dist=1.000 strict_sim=0.000 strict_dist=1.000