全文検索
django.contrib.postgres.search
モジュールのデータベース機能により、PostgreSQLの全文検索エンジンを簡単に使用できます。
このドキュメントの例では、クエリの作成で定義されているモデルを使用します。
searchルックアップ
全文検索を使用する最も簡単な方法は、データベース内の単一の列に対して単一の用語を検索することです。 例えば:
>>> Entry.objects.filter(body_text__search='Cheese')
[<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]
これにより、body_text
フィールドからデータベースにto_tsvector
が作成され、検索語'Cheese'
からplainto_tsquery
が作成されます。どちらも、デフォルトのデータベース検索構成を使用します。 結果は、クエリとベクトルを照合することによって取得されます。
search
ルックアップを使用するには、'django.contrib.postgres'
が:setting: `INSTALLED_APPS` に含まれている必要があります。
SearchVector
- class SearchVector(\*expressions, config=None, weight=None)
単一のフィールドに対する検索は素晴らしいですが、かなり制限されます。 検索しているEntry
インスタンスは、tagline
フィールドを持つBlog
に属しています。 両方のフィールドに対してクエリを実行するには、SearchVector
を使用します。
>>> from django.contrib.postgres.search import SearchVector
>>> Entry.objects.annotate(
... search=SearchVector('body_text', 'blog__tagline'),
... ).filter(search='Cheese')
[<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]
SearchVector
の引数には、任意の Expression またはフィールドの名前を指定できます。 複数の引数はスペースを使用して連結されるため、検索ドキュメントにはそれらすべてが含まれます。
SearchVector
オブジェクトを組み合わせて、再利用することができます。 例えば:
>>> Entry.objects.annotate(
... search=SearchVector('body_text') + SearchVector('blog__tagline'),
... ).filter(search='Cheese')
[<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]
config
およびweight
パラメーターの説明については、検索構成の変更および均等化クエリを参照してください。
SearchQuery
- class SearchQuery(value, config=None, search_type='plain')
SearchQuery
は、ユーザーが提供する用語を、データベースが検索ベクトルと比較する検索クエリオブジェクトに変換します。 デフォルトでは、ユーザーが提供するすべての単語がステミングアルゴリズムを通過し、結果のすべての用語に一致するものが検索されます。
search_type
がデフォルトの'plain'
の場合、用語は個別のキーワードとして扱われます。 search_type
が'phrase'
の場合、用語は1つのフレーズとして扱われます。 search_type
が'raw'
の場合、用語と演算子を使用してフォーマットされた検索クエリを提供できます。 違いと構文については、PostgreSQLの全文検索ドキュメントをお読みください。 例:
>>> from django.contrib.postgres.search import SearchQuery
>>> SearchQuery('red tomato') # two keywords
>>> SearchQuery('tomato red') # same results as above
>>> SearchQuery('red tomato', search_type='phrase') # a phrase
>>> SearchQuery('tomato red', search_type='phrase') # a different phrase
>>> SearchQuery("'tomato' & ('red' | 'green')", search_type='raw') # boolean operators
SearchQuery
の用語を論理的に組み合わせて、柔軟性を高めることができます。
>>> from django.contrib.postgres.search import SearchQuery
>>> SearchQuery('meat') & SearchQuery('cheese') # AND
>>> SearchQuery('meat') | SearchQuery('cheese') # OR
>>> ~SearchQuery('meat') # NOT
config
パラメーターの説明については、検索構成の変更を参照してください。
バージョン2.2の新機能: search_type パラメーターが追加されました。
SearchRank
- class SearchRank(vector, query, weights=None)
これまでのところ、ベクトルとクエリが一致する可能性のある結果を返しました。 何らかの関連性で結果を並べ替えることができます。 PostgreSQLは、クエリ用語がドキュメントに表示される頻度、用語がドキュメント内でどれだけ接近しているか、ドキュメントの一部がドキュメント内でどの程度重要であるかを考慮したランキング機能を提供します。 一致度が高いほど、ランクの値は高くなります。 関連性で注文するには:
>>> from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
>>> vector = SearchVector('body_text')
>>> query = SearchQuery('cheese')
>>> Entry.objects.annotate(rank=SearchRank(vector, query)).order_by('-rank')
[<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]
weights
パラメータの説明については、均等化クエリを参照してください。
検索構成の変更
config
属性を SearchVector および SearchQuery に指定して、別の検索構成を使用できます。 これにより、データベースで定義されているさまざまな言語のパーサーと辞書を使用できます。
>>> from django.contrib.postgres.search import SearchQuery, SearchVector
>>> Entry.objects.annotate(
... search=SearchVector('body_text', config='french'),
... ).filter(search=SearchQuery('œuf', config='french'))
[<Entry: Pain perdu>]
config
の値は、別の列に格納することもできます。
>>> from django.db.models import F
>>> Entry.objects.annotate(
... search=SearchVector('body_text', config=F('blog__language')),
... ).filter(search=SearchQuery('œuf', config=F('blog__language')))
[<Entry: Pain perdu>]
均等化クエリ
すべてのフィールドがクエリで同じ関連性を持っているとは限らないため、さまざまなベクトルを組み合わせる前に、それらの重みを設定できます。
>>> from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
>>> vector = SearchVector('body_text', weight='A') + SearchVector('blog__tagline', weight='B')
>>> query = SearchQuery('cheese')
>>> Entry.objects.annotate(rank=SearchRank(vector, query)).filter(rank__gte=0.3).order_by('rank')
重みは、D、C、B、Aのいずれかの文字である必要があります。 デフォルトでは、これらの重みはそれぞれ番号0.1
、0.2
、0.4
、および1.0
を参照します。 それらに異なる重みを付けたい場合は、4つのフロートのリストを SearchRank にweights
として上記と同じ順序で渡します。
>>> rank = SearchRank(vector, query, weights=[0.2, 0.4, 0.6, 0.8])
>>> Entry.objects.annotate(rank=rank).filter(rank__gte=0.3).order_by('-rank')
パフォーマンス
これらの機能を使用するために特別なデータベース構成は必要ありませんが、数百を超えるレコードを検索している場合は、パフォーマンスの問題が発生する可能性があります。 たとえば、全文検索は、整数のサイズを比較するよりも集中的なプロセスです。
クエリを実行しているすべてのフィールドが1つの特定のモデルに含まれている場合は、使用する検索ベクトルに一致する機能インデックスを作成できます。 PostgreSQLのドキュメントには、全文検索用のインデックスの作成の詳細が記載されています。
SearchVectorField
- class SearchVectorField
このアプローチが遅くなりすぎる場合は、モデルにSearchVectorField
を追加できます。 たとえば、 PostgreSQLのドキュメントで説明されているように、トリガーを設定しておく必要があります。 次に、注釈付きのSearchVector
であるかのようにフィールドにクエリを実行できます。
>>> Entry.objects.update(search_vector=SearchVector('body_text'))
>>> Entry.objects.filter(search_vector='cheese')
[<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]
トリグラムの類似性
検索への別のアプローチは、トリグラムの類似性です。 トリグラムは、3つの連続した文字のグループです。 :lookup: `trigram_similar` ルックアップに加えて、他のいくつかの式を使用できます。
それらを使用するには、PostgreSQLで pg_trgm拡張機能をアクティブ化する必要があります。 TrigramExtension 移行操作を使用してインストールできます。
TrigramSimilarity
- class TrigramSimilarity(expression, string, **extra)
フィールド名または式、および文字列または式を受け入れます。 2つの引数間のトリグラム類似性を返します。
使用例:
>>> 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>]
TrigramDistance
- class TrigramDistance(expression, string, **extra)
フィールド名または式、および文字列または式を受け入れます。 2つの引数間のトリグラム距離を返します。
使用例:
>>> from django.contrib.postgres.search import TrigramDistance
>>> Author.objects.create(name='Katy Stevens')
>>> Author.objects.create(name='Stephen Keats')
>>> test = 'Katie Stephens'
>>> Author.objects.annotate(
... distance=TrigramDistance('name', test),
... ).filter(distance__lte=0.7).order_by('distance')
[<Author: Katy Stevens>, <Author: Stephen Keats>]