検索
Webアプリケーションの一般的なタスクは、ユーザー入力を使用してデータベース内の一部のデータを検索することです。 単純なケースでは、これはオブジェクトのリストをカテゴリでフィルタリングすることです。 より複雑なユースケースでは、均等化、分類、強調表示、複数の言語などを使用した検索が必要になる場合があります。 このドキュメントでは、考えられる使用例と使用できるツールについて説明します。
クエリの作成で使用されているのと同じモデルを参照します。
ユースケース
標準のテキストクエリ
テキストベースのフィールドには、一致する操作の選択肢があります。 たとえば、次のように著者の検索を許可したい場合があります。
>>> Author.objects.filter(name__contains='Terry')
[<Author: Terry Gilliam>, <Author: Terry Jones>]
これは、ユーザーが作成者の名前の正確な部分文字列を知っている必要があるため、非常に脆弱なソリューションです。 より良いアプローチは、大文字と小文字を区別しない一致(:lookup: `icontains` )ですが、これはほんのわずかに優れています。
データベースのより高度な比較機能
PostgreSQLを使用している場合、Djangoはデータベース固有のツールの選択を提供して、より複雑なクエリオプションを活用できるようにします。 他のデータベースには、おそらくプラグインやユーザー定義関数を介して、さまざまなツールの選択肢があります。 現時点では、Djangoにはそれらのサポートは含まれていません。 PostgreSQLのいくつかの例を使用して、データベースが持つ可能性のある機能の種類を示します。
他のデータベースでの検索
django.contrib.postgres が提供するすべての検索ツールは、カスタムルックアップやデータベース関数などのパブリックAPI上に完全に構築されています。 データベースによっては、同様のAPIを許可するクエリを作成できるはずです。 この方法では達成できない特定のことがある場合は、チケットを開いてください。
上記の例では、大文字と小文字を区別しないルックアップの方が便利であると判断しました。 英語以外の名前を扱う場合は、さらに改善するために使用する必要があります :lookup: `アクセントのない比較 ` :
>>> Author.objects.filter(name__unaccent__icontains='Helen')
[<Author: Helen Mirren>, <Author: Helena Bonham Carter>, <Author: Hélène Joy>]
これは、名前の別のスペルと照合している別の問題を示しています。 この場合、非対称性があります。Helen
を検索すると、Helena
またはHélène
が検出されますが、その逆は検出されません。 もう1つのオプションは、:lookup: `trigram_similar` 比較を使用することです。これは、文字のシーケンスを比較します。
例えば:
>>> Author.objects.filter(name__unaccent__lower__trigram_similar='Hélène')
[<Author: Helen Mirren>, <Author: Hélène Joy>]
今、私たちは別の問題を抱えています-「ヘレナボナムカーター」の長い名前ははるかに長いので表示されません。 トリグラム検索では、3文字のすべての組み合わせが考慮され、検索文字列とソース文字列の両方に表示される文字数が比較されます。 長い名前の場合、ソース文字列に表示されない組み合わせが増えるため、厳密一致とは見なされなくなります。
ここでの比較関数の正しい選択は、使用する言語や検索するテキストの種類など、特定のデータセットによって異なります。 私たちが見たすべての例は、ユーザーがソースデータに近いものを(定義を変えることによって)入力する可能性が高い短い文字列にあります。
ドキュメントベースの検索
大きなテキストブロックを検討し始めると、標準のデータベース操作は有用なアプローチではなくなります。 上記の例は文字列に対する操作と考えることができますが、全文検索では実際の単語が調べられます。 使用するシステムによっては、次のアイデアのいくつかを使用する可能性があります。
- 「a」、「the」、「and」などの「ストップワード」を無視します。
- 「ポニー」と「ポニー」が類似していると見なされるように、単語をステミングします。
- テキストに表示される頻度や、タイトルやキーワードなどのフィールドの重要性など、さまざまな基準に基づいて単語に重みを付けます。
検索ソフトウェアを使用するための多くの選択肢がありますが、最も有名なもののいくつかは Elastic と Solr です。 これらは完全なドキュメントベースの検索ソリューションです。 Djangoモデルのデータでそれらを使用するには、データベースIDへの逆参照を含め、データをテキストドキュメントに変換するレイヤーが必要です。 エンジンを使用して検索すると特定のドキュメントが返されると、データベースで検索できます。 このプロセスを支援するように設計されたさまざまなサードパーティライブラリがあります。
PostgreSQLのサポート
PostgreSQLには、独自の全文検索実装が組み込まれています。 他の検索エンジンほど強力ではありませんが、データベース内にあるという利点があるため、分類などの他のリレーショナルクエリと簡単に組み合わせることができます。
django.contrib.postgres モジュールは、これらのクエリを実行するためのいくつかのヘルパーを提供します。 たとえば、クエリで「チーズ」に言及しているすべてのブログエントリを選択できます。
>>> Entry.objects.filter(body_text__search='cheese')
[<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]
フィールドの組み合わせと関連モデルでフィルタリングすることもできます。
>>> Entry.objects.annotate(
... search=SearchVector('blog__tagline', 'body_text'),
... ).filter(search='cheese')
[
<Entry: Cheese on Toast recipes>,
<Entry: Pizza Recipes>,
<Entry: Dairy farming in Argentina>,
]
詳細については、contrib.postgres
全文検索ドキュメントを参照してください。