django/PostgreSQLで全文検索

django postgresql Published at Feb. 8, 2025, 7:07 a.m. by admin@senrigan.org

30分もかからないで全文検索ができてしまって感動した件

SearchQuery, SearchRank, SearchVectorの使用例

   python manage.py shell           
Python 3.12.3 (main, Jan 17 2025, 18:03:48) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.contrib.postgres.search import SearchVector, SearchQuery, SearchRank
>>> from blog.models import Post
>>> vector = SearchVector('title', 'body')
>>> query = SearchQuery('django')
>>> Post.objects.all().annotate(search=vector, rank=SearchRank(vector, query)).filter(search=query).order_by('-rank')
<QuerySet [<Post: django-querysets>]>
>>> print(Post.objects.all().annotate(search=vector, rank=SearchRank(vector, query)).filter(search=query).order_by('-rank').query)

生成されたSQL

SELECT "blog_post"."id", "blog_post"."title", "blog_post"."slug", "blog_post"."body", "blog_post"."status", "blog_post"."author_id", "blog_post"."published_at", "blog_post"."created_at", "blog_post"."updated_at", to_tsvector(COALESCE("blog_post"."title", ) || ' ' || COALESCE("blog_post"."body", )) AS "search", ts_rank(to_tsvector(COALESCE("blog_post"."title", ) || ' ' || COALESCE("blog_post"."body", )), plainto_tsquery(django)) AS "rank" FROM "blog_post" WHERE to_tsvector(COALESCE("blog_post"."title", ) || ' ' || COALESCE("blog_post"."body", )) @@ (plainto_tsquery(django)) ORDER BY 11 DESC

テキスト検索の話でよく出てくる用語

ステミング
語幹処理、musicとかmusicalを同一の語として扱うこと。
レクシーム
語彙素、異なる形態の語彙をまとめる単位。
ストップワード
aとかtheとかonとかofとかそれ自体あまり意味を持たない語。検索エンジンはサーチクエリからストップワードを削除する。
スノーボール
自然言語処理で使われるステミングアルゴリズムのこと。語幹処理でmusicとかmusicalとかの語をひとつのレクシームに正規化するして検索の精度を向上させる。

参考:Full text search