Title: キーワードの読みがなで検索できるようにするには

日本語では、同じ言葉を表記する場合でも、漢字、カタカナ、ひらがななど、使われる文字の種類に揺れがあることがあります。例えば、「心」「こころ」「ココロ」など、時と場合によって表記が異なります。

Solr の初期設定では、「心」という文字を含む文章をキーワード「こころ」で検索しても、表記された文字が異なるため、ヒットしません。しかし、以下に述べる方法で、「表記の文字が異なっていても、読みがなが同じならヒットする」という動作に設定できます。



schema.xml の編集



Solr の日本語用設定「traction_ja」の中にある、schema.xml というファイルをテキストエディタで編集します。

メモ: 日本語用設定「traction_ja」については下のリンク先を参照してください。



text_general フィールド



「text_general」で検索して次の箇所を見つけてください。

<fieldType name="text_general" class="solr.TextField" autoGeneratePhraseQueries="false" positionIncrementGap="100">
  <analyzer>
    <!-- Uncomment this to handle iteration marks: -->
    <!-- <charFilter class="solr.JapaneseIterationMarkCharFilterFactory" /> -->
    <tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt"/>
    <filter class="solr.JapaneseBaseFormFilterFactory"/>
    <filter class="solr.JapanesePartOfSpeechStopFilterFactory" tags="lang/stoptags_ja.txt"/>
    <filter class="solr.CJKWidthFilterFactory"/>
    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-FullNumber.txt"/>
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ja.txt"/>
    <filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4"/>
    <filter class="solr.LowerCaseFilterFactory"/>
 </analyzer>
</fieldType>


<analyzer>...</analyzer> スコープの最後に次の 1 行を挿入します。

<filter class="solr.JapaneseReadingFormFilterFactory" useRomaji="false"/>


「text_general」全体は次のようになります。

<fieldType name="text_general" class="solr.TextField" autoGeneratePhraseQueries="false" positionIncrementGap="100">
  <analyzer>
    <!-- Uncomment this to handle iteration marks: -->
    <!-- <charFilter class="solr.JapaneseIterationMarkCharFilterFactory" /> -->
    <tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt"/>
    <filter class="solr.JapaneseBaseFormFilterFactory"/>
    <filter class="solr.JapanesePartOfSpeechStopFilterFactory" tags="lang/stoptags_ja.txt"/>
    <filter class="solr.CJKWidthFilterFactory"/>
    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-FullNumber.txt"/>
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ja.txt"/>
    <filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.JapaneseReadingFormFilterFactory" useRomaji="false"/> <!-- ここに設定を挿入 -->
 </analyzer>
</fieldType>


text_search フィールド



「text_general」フィールドのすぐ下に「text_search」フィールドがあります。このフィールドの中には type="index"type="query" の 2 つの <analyzer> があります。

<fieldType name="text_search" class="solr.TextField" autoGeneratePhraseQueries="false" positionIncrementGap="100" termVectors="true" termPositions="true" termOffsets="true" termPayloads="true">
  <analyzer type="index">
    <!-- Uncomment this to handle iteration marks: -->
    <!-- <charFilter class="solr.JapaneseIterationMarkCharFilterFactory" /> -->
    <tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt"/>
    <filter class="solr.JapaneseBaseFormFilterFactory"/>
    <filter class="solr.JapanesePartOfSpeechStopFilterFactory" tags="lang/stoptags_ja.txt"/>
    <filter class="solr.CJKWidthFilterFactory"/>
    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-FullNumber.txt"/>
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ja.txt"/>
    <filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt"/>
    <filter class="solr.JapaneseBaseFormFilterFactory"/>
    <filter class="solr.JapanesePartOfSpeechStopFilterFactory" tags="lang/stoptags_ja.txt"/>
    <filter class="solr.CJKWidthFilterFactory"/>
    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-FullNumber.txt"/>
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ja.txt"/>
    <filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4"/>
    <filter class="solr.LowerCaseFilterFactory"/
  </analyzer>
</fieldType>


この type="index"type="query" の両方に上記と同じ 1 行を追加して次のようにします。

<fieldType name="text_search" class="solr.TextField" autoGeneratePhraseQueries="false" positionIncrementGap="100" termVectors="true" termPositions="true" termOffsets="true" termPayloads="true">
  <analyzer type="index">
    <!-- Uncomment this to handle iteration marks: -->
    <!-- <charFilter class="solr.JapaneseIterationMarkCharFilterFactory" /> -->
    <tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt"/>
    <filter class="solr.JapaneseBaseFormFilterFactory"/>
    <filter class="solr.JapanesePartOfSpeechStopFilterFactory" tags="lang/stoptags_ja.txt"/>
    <filter class="solr.CJKWidthFilterFactory"/>
    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-FullNumber.txt"/>
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ja.txt"/>
    <filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.JapaneseReadingFormFilterFactory" useRomaji="false"/> <!-- ここに設定を挿入する -->
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.JapaneseTokenizerFactory" mode="search" userDictionary="lang/userdict_ja.txt"/>
    <filter class="solr.JapaneseBaseFormFilterFactory"/>
    <filter class="solr.JapanesePartOfSpeechStopFilterFactory" tags="lang/stoptags_ja.txt"/>
    <filter class="solr.CJKWidthFilterFactory"/>
    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-FullNumber.txt"/>
    <filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_ja.txt"/>
    <filter class="solr.JapaneseKatakanaStemFilterFactory" minimumLength="4"/>
    <filter class="solr.LowerCaseFilterFactory"/>
    <filter class="solr.JapaneseReadingFormFilterFactory" useRomaji="false"/> <!-- ここに設定を挿入する -->
  </analyzer>
</fieldType>


ファイルを上書き保存して、テキストエディタを終了します。

日本語用設定の再インストール



上記で編集した schema.xml を含む「traction_ja」を Solr に再インストールします。

Solr が起動していることを確認し、次のコマンドを実行します。

Windows 環境の場合

zkcli.bat -cmd upconfig -zkhost 127.0.0.1:9983 -confname traction -confdir C:\MyPathSomewhere\com.traction.extsearch.solr\etc\solr\configsets\traction_ja\conf


Linux 環境の場合

sh zkcli.sh -cmd upconfig -zkhost 127.0.0.1:9983 -confname traction -confdir ~/Somewhere/com.traction.extsearch.solr/etc/solr/configsets/traction_ja/conf


「Solr 検索のインデックス管理」画面の [すべてのドキュメントのフィード] の [開始] ボタンをクリックします。フィードが完了するまでしばらくお待ちください。

再フィードの実行

Solr を再起動します。

以上で設定変更は完了です。

動作テスト



ここでは、「心・ココロ・こころ」と「焼き鳥・ヤキトリ・やきとり」で検索テストを行うため、次の 3 件の記事を投稿しました。

テスト用記事

心・ココロ・こころ



下図のように、「心」「ココロ」「こころ」のどのキーワードで検索しても、3 件の記事すべてがヒットします。

漢字の「心」で検索

「心」で検索

カタカナの「ココロ」で検索

「ココロ」で検索

ひらがなの「こころ」で検索

「こころ」で検索

焼き鳥・ヤキトリ・やきとり



上記のように、「こころ」の検索はうまく行きましたが、「やきとり」の場合は辞書への単語登録が必要になります。

まずは検索テストの結果をみてみましょう。

漢字の「焼き鳥」で検索すると、ひらがなの「やきとり」がヒットしません。

焼き鳥

カタカナの「ヤキトリ」で検索しても、ひらがなの「やきとり」がヒットしません。

ヤキトリ

ひらがなの「やきとり」で検索すると、漢字の「焼き鳥」とカタカナの「ヤキトリ」がヒットしません。

やきとり

この原因は、ひらがな表記の「やきとり」が、日本語解析エンジンの「kuromoji」によって「やき」と「とり」に分割されてしまうことにあります。

この問題を解決するには、「やきとり」という単語を Solr の辞書 (userdict_ja.txt) に登録 します。

やきとり,やきとり,ヤキトリ,名詞


日本語用設定「traction_ja」を zkcli スクリプトで再インストールし、Solr を再起動します。(上述参照)

TeamPage の「Solr 検索のインデックス管理」画面の [すべてのドキュメントのフィード] の [開始] ボタンをクリックし、再フォードが完了するまで待ちます。

漢字の「焼き鳥」、カタカナの「ヤキトリ」、ひらがなの「やきとり」を検索してすべての記事がヒットすることを確認します。

漢字の「焼き鳥」で検索

漢字の「焼き鳥」で検索

カタカナの「ヤキトリ」で検索

カタカナの「ヤキトリ」で検索

ひらがなの「やきとり」で検索

ひらがなの「やきとり」で検索



Attachments:
re_feed.png
example_entries.png
kokoro1.png
kokoro2.png
kokoro3.png
yakitori_1.png
yakitori_2.png
yakitori_3.png
yakitori_4.png
yakitori_5.png
yakitori_6.png
関連記事
Article: DocSolr105 (permalink)
Categories: :DocSolr:FAQ
Date: 2019/04/15; 14時48分31秒 JST

Author Name: TeamPage サポート
Author ID: jpbo