Word ブレーカーとステマーの実装
Microsoft では、さまざまな言語のワード ブレーカーとステマーを提供しています。 このトピックでは、Microsoft が提供するもの以外の言語とロケールに対してカスタム ワード ブレーカーとステマーを実装し、使用する方法について説明します。
注意
カスタム ワード ブレーカーが一時的にサポートされていません。 2018 年 7 月に Windows Server 2019 に変更が加えられたので、Microsoft 署名のない DLL がSearchIndexer.exeによって読み込まれなくなります。 この制限は 2021 年 1 月に解除されました。
このトピックは次のように整理されています。
言語リソース DLL の登録
各言語リソース DLL は、次のエントリ ポイントを実装してエクスポートする必要があります。 DLL は、任意のフォルダーに登録できます。
- DllMain は、DLL への標準エントリ ポイントです。
- DllRegisterServer は、DLL をレジストリに登録します (例: )
regsvr32.exe %SystemRoot%\MyFolder\wordbreaker.dll
- DllCanUnloadNow を使用すると、クライアントはコンポーネント オブジェクト モデル (COM) を介してこのエントリ ポイントを呼び出して、言語リソース DLL をアンロードできるかどうかを判断できます。
- DllUnRegisterServer は、レジストリから DLL を削除します。
言語の登録
レジストリには、インデックスを作成する言語の言語固有のエントリが含まれており、これらのエントリは、言語固有のインデックス作成プロセスとクエリ プロセスの部分を制御します。 これらのレジストリ エントリは、次のレジストリ キーの下にあります。
HKEY_LOCAL_MACHINE
SYSTEM
CurrentControlSet
ContentIndex
Control
Language
Word Beaker の実装
Word ブレーカーは IWordBreaker を実装します。 IWordBreaker::BreakText メソッドは、すべてのテキスト処理と解析を実行します。 ワード ブレーカー コンポーネントを実装するには、言語のヒューリスティックが必要です。 これには、構文と形態に関する情報が含まれます。 除外または含める単語の一覧が必要な場合もあります。 除外された単語の一覧から、言語ロケールのノイズワードのファイルを作成します。 言語に関する考慮事項と、これらの考慮事項がワード ブレーカーの実装に与える影響の詳細については、「 言語と Unicode の考慮事項」を参照してください。
IWordBreaker::BreakText のメインの目的は、すべてのテキストが処理されるまで、またはワード ブレーカーでエラーが発生するまで、TEXT_SOURCEからテキストを継続的に処理することです。 このデータ処理ループでは、 IWordBreaker::BreakText は、そのプロセスの特定のタスクを実行する解析メソッドとユーティリティ メソッドを呼び出します。 たとえば、ドイツ語のワード ブレーカーでは複合語を処理できます。一方、フランス語のワード ブレーカーでは 分音記号や clitic を 処理 できます。 ワード ブレーカーが実行する特定の機能と、これらのタスクの実行に使用する戦略は、その言語の要件によって完全に異なります。
テキストを分割する場合、ワード ブレーカーは、複数の表現を持つ可能性がある単語の "代替" フォームを識別します。 生成された単語の間に意味関係は暗黙的に示されません。 実際、元の単語は代替候補の一覧に含まれていない可能性があります。 代替フォームは、元の単語と同じ位置にインデックスに保存され、同一であることを示します。
文書がインデックスに含まれている場合、各単語には、オフセットを表す整数値、または文書の先頭からの単語の距離が割り当てられます。 クエリ内の単語間の相対距離は、フルテキスト インデックスに格納されているオフセットと比較されます。 クエリ "Where is Kyle's document" は、オフセット n に "Where"、n+1 に "is"、n+2 に "Kyle's"、n+3 に "document" を持つ任意のドキュメントと一致します。 "Kyle のドキュメントは、データ ベース内のどこに提出されていますか?"は、次のように表されます。
Where | : | カイル・カイル |
ドキュメント | 提出 | in | the | データベース データ ベース |
この例では、ワード ブレーカーはインデックスに "Kyle" ("Kyle's") と "database" ("data base") の代替フォームを格納します。 ワード ブレーカーは、インデックス作成プロセス中に次の条件で代替単語を生成して格納します。
- クエリで代替単語が 1 つの単語として表示される可能性がある場合
- ステマーが代替単語から元の単語を派生させる可能性が高くない場合
代替単語形式を生成すると、次のバリエーションに示すように、クエリが文を表し、一致する方法の数が増えます。
- データベースにファイルされた Kyle ドキュメントはどこにありますか
- は、Kyle のドキュメントがデータベースに提出されている場所です
- データ ベースに Kyle ドキュメントが提出されている場所
- データ ベースに Kyle のドキュメントが提出されている場所
WordSink と PhraseSink
Word ブレーカーでは、IWordSink オブジェクトと IPhraseSink オブジェクトを使用して、テキストから抽出したすべての単語と語句を収集して格納します。 ワード ブレーカーは、文書内の元の単語フォームにできるだけ近い形式で単語を格納します。 IPhraseSink は、クエリ時にフレーズを格納します。 語句を使用すると、クエリ結果の関連性が向上します。これは、単語のシーケンスが長いほどまれであり、小さい語句よりも区別が大きくなるためです。 インデクサーは、クエリ時に IPhraseSink に語句を配置すると、語句を単語に分割するワード ブレーカーのインスタンスを作成します。 その後、インデクサーは、語句内の単語がインデックス内の互いに隣接しているかどうかを確認して、フレーズを評価します。 たとえば、位置 x、x+1、x+2、x+3 のインデックスで "ABCD" が発生した場合、クエリで "ABCD" の隣接する部分文字列が送信されると、語句の一致が発生します。 この方法は、インデックス作成時に語句と長い単語を分割し、クエリ時にフレーズを生成する文字ベースのワード ブレーカーに有効です。
改行
区切りは単語間のスペースです。 空白、句読点、書式設定、または言語自体の性質だけで、区切りが発生する可能性があります。 インデクサーで使用される区切りには、単語の終わり (EOW)、文の終わり (EOS)、段落の終わり (EOP)、章の終わり (EOC) の 4 種類があります。 EOW 区切りは既定の区切りです。 各トークンの後、各区切りは、両側の単語間の異なるセマンティック距離を示します。 EOW で区切られた単語には、最も緊密なセマンティック リンクがあり、その後に EOS、EOP、EOC が続きます。 IWordSink::P utBreak への複数の呼び出しは累積的であり、null 単語または文の挿入に似ています。
スケーラビリティ、パフォーマンス、およびセキュリティ
ワード ブレーカーが同時呼び出しに応答する方法は、主にスレッド モデルの選択によって決まります。 インデクサーはシングル スレッド アプリケーションです。 ワード ブレーカーをシングルスレッド環境で動作させるには、"free" または "both" スレッド モデルを使用してワード ブレーカーを記述する必要があります。 Word ブレーカーは、"アパートメント" スレッド モデルを使用して COM に登録することはできません。
ワード ブレーカーはグローバル状態を回避し、ワード ブレーカーのインスタンスにデータを格納することをお勧めします。 ワード ブレーカーの実装に格納する必要があるコンテンツは、パラメーター fQuery と ulMaxTokenSize のみです。 Word ブレーカーは、英語のワード ブレーカーによって確立されたベンチマークの 2 倍以下にする必要があります。 Word ブレーカーのパフォーマンスは、ハードウェア機能の向上によっても向上する必要があります。
インデクサーのWord ブレーカーは、ローカル システムのセキュリティ コンテキストで実行されます。 バッファーを管理し、正しくスタックするように記述する必要があります。 すべての文字列コピーには、バッファー オーバーランから保護するための明示的なチェックが必要です。 常に、バッファーの割り当てられたサイズを確認し、バッファーのサイズに対してデータのサイズをテストする必要があります。 Word ブレーカーでは、IWordBreaker::BreakText メソッドに渡されたテキストが整形式であると想定することはできません。 ワード ブレーカーのトラブルシューティングの詳細については、「 言語リソースとベスト プラクティスのトラブルシューティング」を参照してください。
ステマーの実装
ステマーは IStemmer インターフェイスを実装します。 IStemmer::GenerateWordForms メソッドは、特定の入力ワードに対して、変化した単語フォームのリストを生成します。 ステマー コンポーネントを実装するには、言語のヒューリスティックが必要です。 これには形態に関する情報が含まれます。 除外または含める単語の一覧が必要な場合もあります。 言語に関する考慮事項と、これらの考慮事項がステミング機能の実装に与える影響の詳細については、「 言語と Unicode の考慮事項」を参照してください。
ステマーは、単語のジェニーティブ(所有性)の大文字と小文字を生成しないことをお勧めします。 たとえば、"David" は "David' の代替フォームとして生成されません。ワード ブレーカーでは、"David" と "David' s" の両方が"David's" を解析するときに生成されます。
ステミング機能は 、IWordFormSink オブジェクトを使用して代替単語の一覧を収集します。 IWordFormSink::P utWord は、ステマーから最後の単語を生成します。 いずれの場合も、この最後の単語は IStemmer::GenerateWordForms の入力単語と同じです。 たとえば、"swim" という単語を指定すると、ステマーは 、IWordFormSink::P utAltWord の呼び出しを通じて、"swimming"、"swimmer"、"swims"、"swam"、"swum" という単語形式を生成します。 ステミング機能は、 IWordFormSink::P utWord を介して "swim" を生成します。
スケーラビリティ、パフォーマンス、セキュリティ
ステマーはワード ブレーカーと同様に、"free" スレッド モデルを使用し、スレッド モデルを "free" または "both" に設定して COM に登録する必要があります。Windows Search は、異なるスレッドからステマーの個別のインスタンスを同時に呼び出します。 したがって、ステマーにはインスタンス データが最小限である必要があります。
ステマーの精度は、クエリの関連性に大きな影響を与えます。 ステミング機能がテキストを誤ってステミングすると、クエリによって予測できない不正確な結果が返される可能性があります。 ステマーは、クエリのパフォーマンスに悪影響を与えることなく、1 秒あたり数百のクエリを処理する必要があります。 ステマーのパフォーマンスは、ハードウェア機能を強化することで向上する必要があります。 ステマーのトラブルシューティングの詳細については、「 言語リソースのトラブルシューティング」と「ベスト プラクティス」を参照してください。
Windows Search のステマーは、ローカル セキュリティ コンテキストで実行されます。 バッファーを管理し、正しくスタックするように書き込む必要があります。 すべての文字列コピーには、バッファー オーバーランを防ぐために明示的なチェックが必要です。 バッファーの割り当てられたサイズを常に確認し、バッファーのサイズに対してデータのサイズをテストする必要があります。
関連トピック