EXTENSIONS

RONDHUIT Solr プラグイン(Solr 9)
無料

ご利用にはKandaSearchへの
ユーザー登録(無料)が必要です

Solr Plugin
RONDHUIT Solr プラグイン(Solr 9)

最新バージョン: 2.4.0

開発者: RONDHUIT

ダウンロード数: 48

最終更新日: 2023-10-31

Copyright: RONDHUIT Co.,LTD

最新バージョン: 2.4.0

開発者: RONDHUIT

ダウンロード数: 48

最終更新日: 2023-10-31

Copyright: RONDHUIT Co.,LTD

ロンウイットが開発したApache Solrのプラグインです。日本語の検索機能を強化しています。

前処理やクエリ処理で動作するロンウイットの日本語処理プラグインでは、

  • CharFilter, Tokenizer, TokenFilter
  • UpdateRequestProcessor
  • QParserPlugin
  • SearchComponent

を通して、日本語独特の表記揺れを吸収し、検索漏れの事故の未然防止や、ちょっとした工夫で効率や使い勝手を向上させながら、日本語の検索機能を強化します。

RONDHUIT Solr プラグイン(Solr 9)

内容

1. SolrPlugin の CharFilter, Tokenizer, TokenFilter

1. SolrPlugin の CharFilter, Tokenizer, TokenFilter

CharFilters

JavaNormalizerCharFilter

Normalizerクラスを使用したオフセット補正機能対応のCharFilterです。Normalizerとはテキストのソートや検索が容易になるように Unicode テキストをそれと等価な合成形式または分解形式に変換する機能です。

変換例

△は半角スペース

変換前 変換後
あか”る あがる
あ△か”△る あ△が△る
A:BC ÄBC
A:△B△C Ä△B△C

設定

パラメータ 説明
form NFC(Normalize Function Composite)
NFD(Normalize Function Decomposite)
NFKC(Normalization Form Compatibility Composition)
NFKD(Normalization Form Compatibility Decomposition)
maxBlockChars 一回で処理可能な最大文字数

schema.xml/managed-schemaの設定例(正規分解とそれに続く正規合成を実行します):

<fieldType name="text_ja" class="solr.TextField" positionIncrementGap="100">
  <analyzer>
    <charFilter class="com.rondhuit.solr.analysis.JavaNormalizerCharFilterFactory" form="NFC" maxBlockChars="8192"/>
    <tokenizer class="solr.JapaneseTokenizerFactory"/>
  </analyzer>
</fieldType>

注意

正規化された文字を含む単語のハイライトはずれる可能性があります(制限事項)。正規化された文字を含まない単語のハイライトはずれません。正規化された文字を含む単語をハイライトする可能性があるときは、MappingCharFilter の利用をご検討ください。

KanjiNumberCharFilter

“四十七”などの漢数字を”47″という算用数字(アラビア数字)に正規化します。これにより、漢数字と算用数字どちらが使われている文書でも、漢数字または算用数字を使って検索できるようになります。オフセットも正しく計算するため、ハイライトずれも起きません。

変換例

参考までに JapaneseNumberFilter と出力が異なる場合、それも記載しておきます。JapaneseNumberFilter はトークンフィルターのため、JapaneseTokenizer を前段に使うことが条件となっています。

変換前 変換後 JapaneseNumberFilterで出力が異なるもの
四七 47
四十七 47
四百七 407
四〇七 407
四千十七 4017
一億 100000000
1億 100000000
一千億 100000000000
壱億弐千参百四拾萬 12340000 壱, 億, 弐, 1000, 参, 104, 拾, 萬

設定

schema.xml/managed-schemaの設定例:

<fieldType name="ja_number" class="solr.TextField" positionIncrementGap="100">
  <analyzer>
    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ja.txt"/>
    <charFilter class="com.rondhuit.solr.analysis.KanjiNumberCharFilterFactory"/>
    <tokenizer class="solr.JapaneseTokenizerFactory"/>
  </analyzer>
</fieldType>

KatakanaStemCharFilter

JapaneseKatakanaStemFilterのCharFilterバージョンです。CharFilterなので、N-gramにもカタカナ語末尾の長音記号の表記揺れに対応できます。また、オフセット補正機能付きなので、ハイライト表示もずれがなく行うことが可能です。

変換例

変換前 変換後
サーバー サーバ
コンピューター コンピュータ
サーファー サーファ

設定

schema.xml/managed-schemaの設定例:

<fieldType name="text_cjk" class="solr.TextField" positionIncrementGap="100">
  <analyzer>
    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ja.txt"/>
    <charFilter class="com.rondhuit.solr.analysis.KatakanaStemCharFilterFactory"/>
    <tokenizer class="solr.JapaneseTokenizerFactory"/>
  </analyzer>
</fieldType>

NakaguroCharFilter

外来語に使われる中黒(全角 U+30FB, 半角 U+FF65)の有無を正規化し、相互にヒットするようにします。 オフセット補正にも対応するので、ハイライトずれは起きません。

変換例

変換前 変換後
オープンソース・ソフトウェア オープンソースソフトウェア
ザ・ビートルズ ザビートルズ

設定

schema.xml/managed-schemaの設定例:

<fieldType name="gairaigo" class="solr.TextField" positionIncrementGap="100">
  <analyzer>
    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ja.txt"/>
    <charFilter class="com.rondhuit.solr.analysis.NakaguroCharFilterFactory"/>
    <tokenizer class="solr.JapaneseTokenizerFactory"/>
  </analyzer>
</fieldType>

OdorijiCharFilter

「時々」と「時時」など、漢字/ひらがな/カタカナ文字の繰り返し記号を使用するいわゆる 「踊り字」のサポート機能です。踊り字を含む単語を踊り字を含まない単語に正規化することで、踊り字を含む文書も含まない文書も、踊り字を含む単語/含まない単語どちらで検索してもヒットするようになります。

変換例

変換前 変換後 備考 JapaneseIterationMarkCharFilterで出力が異なるもの
様々 様様
本日から大々々売り出し 本日から大大大売り出し 「々々」の直前が漢字1文字のため 本日から大大々売り出し
部分々々 部分部分 「々々」の直前が漢字2文字のため
つゝみ つつみ
いすゞ いすず
あ々 あ々 「々」はひらがなには適用されない ああ
ツヽジ ツツジ
つゝゞ つつづ
1つゞゝ 1つづつ

設定

schema.xml/managed-schemaの設定例:

<fieldType name="text_ja" class="solr.TextField" positionIncrementGap="100">
  <analyzer>
    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ja.txt"/>
    <charFilter class="com.rondhuit.solr.analysis.OdorijiCharFilterFactory"/>
    <tokenizer class="solr.JapaneseTokenizerFactory"/>
  </analyzer>
</fieldType>

ProlongedSoundMarkCharFilter

全角カタカナまたはひらがなのうしろの下表の文字を長音記号(U+30FC “KATAKANA-HIRAGANA PROLONGED SOUND MARK”)に正規化するCharFilterです。半角カタカナのうしろは関知しないので、必要ならMappingCharFilterなどで半角カタカナを全角カタカナに変換する必要があります。

文字コード 文字名称 文字
U+002D HYPHEN-MINUS -
U+FF0D FULLWIDTH HYPHEN-MINUS
U+2010 HYPHEN
U+2011 NON-BREAKING HYPHEN
U+2012 FIGURE DASH
U+2013 EN DASH
U+2014 EM DASH
U+2015 HORIZONTAL BAR
U+207B SUPERSCRIPT MINUS
U+208B SUBSCRIPT MINUS

設定

schema.xml/managed-schemaの設定例:

<fieldType name="text_ja" class="solr.TextField" positionIncrementGap="100">
  <analyzer type="index">
    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ja.txt"/>
    <tokenizer class="solr.JapaneseTokenizerFactory"/>
  </analyzer>
  <analyzer type="query">
    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ja.txt"/>
    <charFilter class="com.rondhuit.solr.analysis.ProlongedSoundMarkCharFilterFactory"/>
    <tokenizer class="solr.JapaneseTokenizerFactory"/>
  </analyzer>
</fieldType>

WarekiCharFilter

和暦年を西暦年に正規化するCharFilterです。検索時に和暦と西暦を相互ヒットさせることが可能です。飛鳥時代(大化元年)から現代(令和)までをサポートします。 年数は半角算用数字でなければならないため、通常、KanjiNumberCharFilterと組み合わせて用います。 オフセットも正しく計算するため、ハイライトずれも起きません。

変換例

変換前 変換後
大化元年
大化1年
645年 元年でも1年でもOK
明治30年
明治三十年
明治参拾年
1897年 KanjiNumberCharFilterが必要
昭和64年
平成元年
1989年 昭和と平成が重なった年もOK

設定

schema.xml/managed-schemaの設定例:

<fieldType name="wareki" class="solr.TextField" positionIncrementGap="100">
  <analyzer>
    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ja.txt"/>
    <charFilter class="com.rondhuit.solr.analysis.KanjiNumberCharFilterFactory"/>
    <charFilter class="com.rondhuit.solr.analysis.WarekiCharFilterFactory"/>
    <tokenizer class="solr.JapaneseTokenizerFactory"/>
  </analyzer>
</fieldType>

関連項目

Wikipedia 元号一覧 (日本)

Tokenizers

JaBuzzPhraseTokenizer

文章中で一定以上連続するアルファベット、漢字やカタカナ文字、またはカタカナ+漢字ミックスは専門用語と見なしてトークンを抽出します。抽出された専門用語はファセット、クラスタリング、レコメンド、サジェスト(オートコンプリート)、もしかして検索などで活用できます。

以下のパラメータが指定できます。

パラメータ デフォルト 説明
minAlphabetLen 4 抽出するアルファベットの最小連続文字列数。
minKatakanaLen 7 抽出するカタカナの最小連続文字列数。
minKanjiLen 4 抽出する漢字の最小連続文字列数。
minMixLen 4 抽出する漢字とカタカナ混合の最小連続文字列数。
allowMix true 漢字とカタカナの混合を抽出対象とみなすか否か。

分割例

トークナイズ前 トークナイズ後 備考
Solr大規模分散検索オープンソース Solr / 大規模分散検索オープンソース 専門用語が漢字+カタカナミックス
(allowMix="true"に設定時)
大規模分散検索Solrオープンソース 大規模分散検索 / Solr / オープンソース
Information関東関西大学インフォメーション情報処理学科 Information / 関東関西大学 / インフォメーション / 情報処理学科 allowMix="false"に設定時
etc国立私立大学カタカナ関東関西大学インフォメーション 国立私立大学 / 関東関西大学 / インフォメーション 「etc」、「カタカナ」は脱落
(allowMix="false"に設定時)

設定

schema.xml/managed-schemaの設定例:

<fieldType name="text_buzz" class="solr.TextField" positionIncrementGap="100">
  <analyzer>
    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ja.txt"/>
    <tokenizer class="com.rondhuit.solr.analysis.JaBuzzPhraseTokenizerFactory"
               minAlphabetLen="4" minKatakanaLen="5" minKanjiLen="4" allowMix="false"/>
  </analyzer>
</fieldType>

Kanji1GramTokenizer

検索性能を考慮した、漢字のみ1-gramで処理するTokenizerです。1-gram フィールドを安易に使用すると、検索性能を大きく劣化させます。日本語環境で1文字検索をしたい場合、漢字1文字となることがほとんどですので、「1文字検索があり得るが、検索性能を落としたくない」という場合に便利です。

independentOnly=trueの場合(デフォルト)、漢字が2文字以上連続している場合除外されます。independentOnly=falseの場合、全ての漢字を対象とします。

分割例

トークナイズ前 トークナイズ後 備考
昨日は休みでした 昨 / 日 / 休 independentOnly=false、全ての漢字が1-gramで処理、漢字以外は脱落
昨日は休みでした independentOnly=true、「昨日」は漢字2文字が連続しているため脱落

設定

schema.xml/managed-schemaの設定例:

<fieldType name="text_1k" class="solr.TextField" positionIncrementGap="100">
  <analyzer>
    <tokenizer class="com.rondhuit.solr.analysis.Kanji1GramTokenizerFactory" independentOnly="false"/>
  </analyzer>
</fieldType>

KnownWordsTokenizer

ルールベースの固有表現抽出を行うTokenizerで、FST(Finite State Transducer)上に作成された辞書に掲載されているキーワードだけをトークナイズします。

固有表現抽出機能とは?

固有表現抽出とは、人名、地名、組織名などの固有名詞を、属性付きで自然言語の文書から抽出するタスクです。 固有名詞やキーワードを辞書に登録することで、辞書に記載した単語だけをコンテンツから抽出しファセット表示の軸などとして用いることができます。 固有表現抽出をSolrと組み合わせると、特にフィールドの少ない企業内検索に多大な威力を発揮します。 企業ドメインの専門用語や固有表現をあらかじめ抽出しておくことで、ユーザはその専門用語を使ってドキュメントの絞り込みができるようになります。

分割例

辞書に登録されている単語だけがコンテンツから抽出されます。

トークナイズ前 トークナイズ後
安倍首相は外遊先のフィリピンで「本当は消費税を上げたくない」と本音を漏らした。 安倍首相 / フィリピン / 消費税

設定

schema.xml/managed-schemaの設定例:

<fieldType name="text_known" class="solr.TextField" positionIncrementGap="100">
  <analyzer type="index">
    <tokenizer class="com.rondhuit.solr.analysis.KnownWordsTokenizerFactory"
               words="javaclasses.txt" ignoreCase="false"/>
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.KeywordTokenizerFactory"/>
  </analyzer>
</fieldType>

known_org.txt (辞書)の設定例:

安倍首相    
フィリピン    
消費税

TokenFilter

JaReadingInjectionFilter

ReadingAttributeの読みをローマ字に変換してCharTermAttributeに入れます。ReadingAttributeが空の場合は、CharTermAttributeを可能な範囲でローマ字に変換します。

変換例

変換前 変換後
東京 tōkyō

設定

schema.xml/managed-schemaの設定例:

<!-- 漢字トークンの読みをローマ字に変換 -->
<fieldType name="text_ja_spell" class="solr.TextField">
  <analyzer>
    <tokenizer class="solr.JapaneseTokenizerFactory"/>
    <filter class="com.rondhuit.solr.analysis.JaReadingInjectionFilterFactory"/>
  </analyzer>
</fieldType>

JaStringTypeFilter

トークン文字列の「タイプ」(ひらがな、カタカナ、漢字、アルファベット)を基準にフィルタリングします。 保持対象のタイプは以下の該当パラメータをtrueに指定してください。

  • keepKatakana
  • keepKanji
  • keepHiragana
  • keepAlphabet

変換例

変換前 変換後 保持対象のタイプ
トウキョウ トウキョウ keepKatakana
東京 keepKatakana
とうきょう keepKatakana
tokyo keepKatakana
東京 東京 keepKanji
とうきょう とうきょう keepHiragana
tokyo tokyo keepAlphabet

設定

schema.xml/managed-schemaの設定例:

<fieldType name="katakana" class="solr.TextField" positionIncrementGap="100">
  <analyzer>
    <tokenizer class="solr.JapaneseTokenizerFactory"/>
    <filter class="com.rondhuit.solr.analysis.JaStringTypeFilterFactory" keepKatakana="true"/>
  </analyzer>
</fieldType>

NGramKatakanaStemFilter

N-gram系トークナイザーで使えるGosenKatakanaStemFilterで、カタカナのトークンの末尾に長音(ー)があれば除去します。

設定

schema.xml/managed-schemaの設定例:

<fieldType name="text_2g" class="solr.TextField" positionIncrementGap="100">
  <analyzer>
    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ja.txt"/>
        <tokenizer class="solr.NGramTokenizerFactory" minGramSize="2" maxGramSize="2"/>
    <filter class="com.rondhuit.solr.analysis.NGramKatakanaStemFilterFactory"/>
  </analyzer>
</fieldType>

JaSuggestFilter

検索語サジェスチョン専用のTokenFilter。

検索語サジェスチョンでは日本語IMEでの入力途中・変換前の文字列に対して日本語形態素解析が行われるため、半端に分断されてしまったトークンを連結します。トークン連結後に、IME入力途中でもマッチする工夫を凝らした、ローマ字変換を行います。また、同じ読みの漢字対応として、ローマ字に加えて、異なる漢字として識別します。

前提

  • 事前にMappingCharFilter等で全角アルファベットを半角アルファベットに変換しておく。
  • JapaneseTokenizerのうしろに配置する。

オプション

  • concatKanjiToken属性に、漢字も含めてトークン連結を行う(true)か否か(false)かを指定(デフォルトはfalse)。
  • matchExactKanji属性に、同じ読みの漢字対応として、漢字を正確にマッチさせる(true)か否か(false)かを指定(デフォルトはtrue)。

設定

schema.xml/managed-schemaの設定例:

<fieldType name="suggest_ja" class="solr.TextField" positionIncrementGap="100">
  <analyzer>
    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ja.txt"/>
    <tokenizer class="solr.JapaneseTokenizerFactory"/>
    <filter class="com.rondhuit.solr.analysis.JaSuggestFilterFactory" concatKanjiToken="false" matchExactKanji="true"/>
  </analyzer>
</fieldType>

UniqueTokenFilter

同一の文字列を持つトークンを除去するTokenFilter

JaBuzzPhraseTokenizerやKanji1GramTokenizer、KnownWordsTokenizerなどで、同じ文字列を持つトークンが複数個生成されてしまい、ランキングの都合からそれらを除去したい場合に利用します。

設定

schema.xml/managed-schemaの設定例:

<fieldType name="suggest_ja" class="solr.TextField" positionIncrementGap="100">
  <analyzer>
    <charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ja.txt"/>
    <tokenizer class="com.rondhuit.solr.analysis.JaBuzzPhraseTokenizerFactory" minAlphabetLen="4" minKatakanaLen="5" minKanjiLen="4"/>
    <filter class="com.rondhuit.solr.analysis.UniqueTokenFilterFactory"/>
  </analyzer>
</fieldType>

2. SolrPlugin の UpdateRequestProcessor

AddFieldsFromRequestParametersUpdateRequestProcessor

インデクシング時リクエストのすべてのドキュメントに対し、fieldParam 中の name で指定されたパラメータのフィールドに、value で指定されたパラメータの値を追加します。シングルコア環境でマルチテナントを実現するのに便利に使えます。検索時は CheckIndexSubsetComponent を組み合わせてご利用ください。

設定

solrconfig.xmlの設定を以下のように行っておき、

  <updateRequestProcessorChain name="addReqParams">
    <processor class="com.rondhuit.solr.update.AddFieldsFromRequestParametersUpdateRequestProcessorFactory">
      <lst name="fieldParam">
        <str name="name">affrp.field</str>
        <str name="value">affrp.value</str>
      </lst>
      <bool name="ignore">false</bool>
    </processor>
    <processor class="solr.RunUpdateProcessorFactory" />
    <processor class="solr.LogUpdateProcessorFactory" />
  </updateRequestProcessorChain>

インデクシング時は

?update.chain=addReqParams&affrp.field=_member&affrp.value=5508abc7

などと呼び出すと、 _member フィールドに 5508abc7 が埋め込まれます。指定されたパラメータが見つからない場合、ignore の設定にしたがいます。ignore が false(デフォルト)のとき、例外を発行し、インデクシングプロセスが失敗します。ignore が true のとき、インデクシングを続行します。

fieldParam の部分は次のように複数指定できます。

  <updateRequestProcessorChain name="addReqParams">
    <processor class="com.rondhuit.solr.update.AddFieldsFromRequestParametersUpdateRequestProcessorFactory">
      <lst name="fieldParam">
        <str name="name">affrp.field1</str>
        <str name="value">affrp.value1</str>
      </lst>
      <lst name="fieldParam">
        <str name="name">affrp.field2</str>
        <str name="value">affrp.value2</str>
      </lst>
      <bool name="ignore">false</bool>
    </processor>
    <processor class="solr.RunUpdateProcessorFactory" />
    <processor class="solr.LogUpdateProcessorFactory" />
  </updateRequestProcessorChain>

この場合、affrp.field1, affrp.value1, affrp.field2, affrp.value2 のどれか一つでもパラメータが見つからない場合、前述の ignore の設定にしたがった動作となります。

HeadsFieldValueUpdateProcessor

maxLength に達するまで StrField や TextField のフィールド値を保持し、maxLength に達した以降の値は切り捨てます。alternateField をサポートしていない Unified Highlighter 利用時に、alternateField の代用として使うと便利です。

設定

Solr の FieldMutatingUpdateProcessorFactory を継承しているので、処理対象とするフィールドを fieldName, typeName, fieldRegex, typeClass で指定できるほか、 exclude で処理対象外のフィールドを指定することができます。たとえば、以下のような設定をしておき

  <updateRequestProcessorChain name="heads">
    <processor class="com.rondhuit.solr.update.HeadsFieldValueUpdateProcessorFactory">
      <str name="typeClass">solr.StrField</str>
      <int name="maxLength">100</int>
    </processor>
    <processor class="solr.RunUpdateProcessorFactory" />
    <processor class="solr.LogUpdateProcessorFactory" />
  </updateRequestProcessorChain>

インデクシング時は

?update.chain=heads

と呼び出せば、全StrFieldのフィールドを対象に、フィールド値の長さが100に達した以降の値を切り捨てます。

KnownWordsExtractUpdateProcessor

srcで指定したフィールド名(カンマ区切りで複数指定可能)からdestのwordsで指定したファイルに一覧されているキーワードを抽出し、destのfieldsに指定したフィールドに出力します。destのfieldsのフィールドはmultiValuedでなければなりません。 destのfieldsとwordsはカンマ区切りで複数指定が可能ですが、指定数は同じにしなければなりません。また、指定順序は一致させなければなりません。fieldsのフィールド名指定には’’(アスタリスク)が使えます。その場合、 ‘’はsrcのフィールド名に置き換えられます。

下記の設定例で説明すると、textフィールドからknown-locations.txtに一覧されている地名が抽出されてtext_locationフィールドに出力され、known_persons.txtに一覧されている人名が抽出されてtext_personフィールドに出力されます。titleフィールドからも同様の抽出が行われ、地名と人名がそれぞれtitle_location、title_personフィールドに出力されます。

辞書にアルファベット文字がある場合、その辞書の表記の大文字小文字の区別はデフォルトで尊重されます。大文字小文字の区別を行いたくない場合は、下記設定例のように ignoreCase=true を指定します。

抽出例

src dest person dest location
こんにちは、佐藤さん。あら、こんにちは、鈴木さん。 佐藤、鈴木
陽気な佐藤さんと東京都の田中さん 佐藤、田中 東京都

設定

solrconfig.xmlの設定:

<updateRequestProcessorChain name="known4">
 <processor class="com.rondhuit.solr.update.KnownWordsExtractUpdateProcessorFactory">
   <bool name="ignoreCase">true</bool>
   <str name="src">text,title</str>
   <lst name="dest">
     <str name="fields">*_location,*_person</str>
     <str name="words">known-locations.txt,known-persons.txt</str>
   </lst>
 </processor>      
 <processor class="solr.UniqFieldsUpdateProcessorFactory">
   <str name="fieldName">plan_sm</str>
 </processor>
 <processor class="solr.RunUpdateProcessorFactory" />
 <processor class="solr.LogUpdateProcessorFactory" />
</updateRequestProcessorChain>

NormalizeFieldByAnalyzerUpdateProcessor

srcで指定したフィールド値をfieldTypeで指定したフィールド型のインデックスAnalyzerで処理し、その結果文字列をdestで指定したフィールドに出力します。srcはmultiValuedでもよいです。インデックスAnalyzerで処理した際に、出力されるトークンは連結されて出力文字列となりますが、N番目のトークンの終了オフセットとN+1番目のトークンの開始オフセットが異なる場合、その間隙を埋めるべく差分の数のスペースが付加されます。

抽出例

src dest
ABC DEF GHIJKL abc def ghijkl

設定

solrconfig.xmlの設定:

<updateRequestProcessorChain name="analyzerMV">
 <processor class="com.rondhuit.solr.update.NormalizeFieldByAnalyzerUpdateProcessorFactory">
   <str name="src">text_sm</str>
   <str name="dest">suggest_sm</str>
   <str name="fieldType">text_low</str>
 </processor>
 <processor class="solr.RunUpdateProcessorFactory" />
 <processor class="solr.LogUpdateProcessorFactory" />
</updateRequestProcessorChain>

schema.xml/managed-schemaの設定:

<fieldType name="text_low" class="solr.TextField" positionIncrementGap="100">
  <analyzer>
    <tokenizer class="solr.WhitespaceTokenizerFactory"/>
    <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>
</fieldType>

RegexCheckFieldUpdateProcessor

fieldで指定したフィールド値をacceptまたはdenyで指定した正規表現のパターンでマッチ判定を行い、当該ドキュメントを受け入れる(accept)か拒否する(deny)かを決めます。fieldはmultiValuedでもよいです。acceptを指定した場合、fieldのフィールド値がマッチしたら当該ドキュメントを受け入れます。denyを指定した場合、fieldのフィールド値がマッチしたら当該ドキュメントを拒否します。ドキュメントにfieldのフィールドが存在しない場合、「マッチしない」と解釈され、acceptまたはdenyが判定されます。

抽出例

フィールド値(複数行はMultiValued) 正規表現 ドキュメントを受け入れるか拒否するか
{!lucene q.op=AND df=myfield}hello, Solr! accept={!.}. accept
hello, Solr! accept={!.}. deny
(null) accept={!.}. deny
hello, Solr! deny={!.}. accept
{!lucene q.op=AND df=myfield}hello, Solr! deny={!.}. deny
(null) deny={!.}. accept
hello, Lucene!
{!lucene q.op=AND df=myfield}hello, Solr!
accept={!.}. accept
hello, Solr!
hello, Lucene!
accept={!.}. deny
hello, Solr!
hello, Lucene!
deny={!.}. accept
hello, Lucene!
{!lucene q.op=AND df=myfield}hello, Solr!
deny={!.}. deny

設定

solrconfig.xmlの設定:

<updateRequestProcessorChain name="regexAccept">
  <processor class="com.rondhuit.solr.update.RegexCheckFieldUpdateProcessorFactory">
    <str name="field">text_sm</str>
    <str name="accept">\{!.*\}.*</str>
  </processor>
  <processor class="solr.RunUpdateProcessorFactory" />
  <processor class="solr.LogUpdateProcessorFactory" />
</updateRequestProcessorChain>
<updateRequestProcessorChain name="regexDeny">
  <processor class="com.rondhuit.solr.update.RegexCheckFieldUpdateProcessorFactory">
    <str name="field">text_sm</str>
    <str name="deny">\{!.*\}.*</str>
  </processor>
  <processor class="solr.RunUpdateProcessorFactory" />
  <processor class="solr.LogUpdateProcessorFactory" />
</updateRequestProcessorChain>

RegexCopyUpdateProcessor

srcのソースフィールドの一部の文字列をpatternの正規表現とreplacementで抽出し、destのフィールドにコピーしてdestフィールドを作成します。複数のフィールドの一部を組み合わせてIDフィールドを作成するようなときに用いることができます。

dest フィールドが multiValued か否か、connectionStr 指定のあるなしの組み合わせで、次の4通りの動作となります。

dest connectionStr 説明
multiValued == true なし multiValuedでコピー
multiValued == true あり connectionStrで接続しながら一行にコピー
multiValued == false なし connectionStrで接続しながら一行にコピー
multiValued == false あり connectionStrで接続しながら一行にコピー
overwrite 説明
true destフィールドに値があってもsrcから生成した文字列で上書きコピーする。
false(デフォルト) destフィールドに値があるときは、その値を採用する。

設定

solrconfig.xmlの設定:

<updateRequestProcessorChain name="copy">
  <processor class="com.rondhuit.solr.update.RegexCopyUpdateProcessorFactory">
    <lst>
      <str name="dest">id1_s</str>
      <bool name="overwrite">true</bool>
      <str name="connectionStr">#</str>
      <arr name="srcs">
        <lst name="src">
          <str name="name">f1_s</str>
          <str name="pattern">(.*)</str>
          <str name="replacement">$1</str>
        </lst>
        <lst name="src">
          <str name="name">f2_s</str>
          <str name="pattern">.(.).*</str>
          <str name="replacement">$1</str>
        </lst>
      </arr>
    </lst>
    <lst>
      <str name="dest">id2_s</str>
      <lst name="src">
        <str name="name">f3_s</str>
        <str name="pattern">\s+(.+)#(.+)</str>
        <str name="replacement">$2$1</str>
      </lst>
    </lst>
    <lst>
      <str name="dest">id3_sm</str>
      <arr name="srcs">
        <lst name="src">
          <str name="name">f1_s</str>
          <str name="pattern">(.*)</str>
          <str name="replacement">$1</str>
        </lst>
        <lst name="src">
          <str name="name">f2_s</str>
          <str name="pattern">.(.).*</str>
          <str name="replacement">$1</str>
        </lst>
      </arr>
    </lst>
    <lst>
      <str name="dest">id4_sm</str>
      <str name="connectionStr">#</str>
      <arr name="srcs">
        <lst name="src">
          <str name="name">f1_s</str>
          <str name="pattern">(.*)</str>
          <str name="replacement">$1</str>
        </lst>
        <lst name="src">
          <str name="name">f2_s</str>
          <str name="pattern">.(.).*</str>
          <str name="replacement">$1</str>
        </lst>
      </arr>
    </lst>
  </processor>
  <processor class="solr.RunUpdateProcessorFactory" />
  <processor class="solr.LogUpdateProcessorFactory" />
</updateRequestProcessorChain>

抽出例

上記設定の下、以下のように抽出されます。

src dest 説明
f1_s=”Hello!”
f2_s=”1234567890″
old id1_s=”existData”
new id1_s=”Hello!#2″
f1_s全体とf2_sの二番目文字のみconnectionStr=#で連結。overwrite=trueのため元のフィールド値は上書き
f3_s=” 123#4567890″ old id2_s=”existData”
new id2_s=”existData”
overwrite=falseのため元のフィールド値を保持。もし、overwrite=trueだったとしたら、f3_sで”#”前後の文字列を逆に連結し、id2_s=”4567890123″となる
f1_s=”Hello!”
f2_s=”1234567890″
id3_sm=
“Hello!”
“2”
connectionStrが設定されていないのでmultiValuedでコピー
f1_s=”Hello!”
f2_s=”1234567890″
id4_sm=”Hello!#2″ f1_s全体とf2_sの二番目文字のみconnectionStr=#で連結

関連項目

RegexReplaceProcessorFactory

URLDecodeUpdateProcessor

fieldで指定したフィールドのURL文字列値をURLDecoder.decode(String, String)を使ってURLデコードします。encoding(デフォルトはUTF-8)でエンコーディングを指定します。

抽出例

変換前 変換後
http://www.rondhuit.con/
%E6%9C%80%E5%88%9D%E3%81%AE%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80/
%E6%AC%A1%E3%81%AE%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80/index.html
http://www.rondhuit.con/最初のフォルダ/次のフォルダ/index.html

設定

solrconfig.xmlの設定:

<updateRequestProcessorChain name="url">
  <processor class="com.rondhuit.solr.update.URLDecodeUpdateProcessorFactory">
    <str name="field">url_s</str>
    <str name="encoding">UTF-8</str>
  </processor>
  <processor class="solr.RunUpdateProcessorFactory" />
  <processor class="solr.LogUpdateProcessorFactory" />
</updateRequestProcessorChain>

UTCNormalizeUpdateProcessor

srcのnameソースフィールドの日付文字列をUTCに変換してdestのフィールドを作成します。ソースフィールドの日付文字列は、いかなるタイムゾーンを用いて表現されていてもよいです。destへはUTCに変換されます。ソースフィールドのタイムゾーンはsrcのtimezoneで指定します。また、ソースフィールドの日付文字列の書式は、srcのformatsに複数指定できます。書式は、SimpleDateFormatに従います。使用可能な書式(MMMなど)は、Solrサーバのロケールによって制限を受けます。

抽出例

src desc
2010/1/10 2010-01-09T15:00:00Z
2010/1/10 12:34:56 2010-01-10T03:34:56Z
2010-2-10 2010-02-09T15:00:00Z
2010-2-10 12:34:56 2010-02-10T03:34:56Z
2010年3月10日 2010-03-09T15:00:00Z
2010年3月10日 12:34:56 2010-03-10T03:34:56Z

設定

solrconfig.xmlの設定:

<updateRequestProcessorChain name="utc">
  <processor class="com.rondhuit.solr.update.UTCNormalizeUpdateProcessorFactory">
    <str name="dest">utc_dt</str>
    <lst name="src">
      <str name="name">srcdt_s</str>
      <str name="timezone">JST</str>
      <arr name="formats">
        <str>yyyy/MM/dd HH:mm:ss</str>
        <str>yyyy/MM/dd</str>
        <str>yyyy-MM-dd HH:mm:ss</str>
        <str>yyyy-MM-dd</str>
        <str>yyyy年MM月dd日 HH:mm:ss</str>
        <str>yyyy年MM月dd日</str>
      </arr>
    </lst>
  </processor>
  <processor class="solr.RunUpdateProcessorFactory" />
  <processor class="solr.LogUpdateProcessorFactory" />
</updateRequestProcessorChain>

dest パラメータは必須で、UTC日付文字列として生成するフィールド名を指定します。src は以下の通りです。

パラメータ 説明
name(必須) UTC日付に変換される元のフィールド名
timezone nameの日付フィールドのtimezoneに指定可能なタイムゾーンID。省略した場合は、Solrサーバが稼働しているマシンのタイムゾーンとなる
formats(必須) nameの日付フィールドの書式を1つ以上指定する。複数指定することで、nameフィールドの日付書式が数パターンあっても対応できる。書式は、SimpleDateFormatに従う

3. SolrPlugin の QParserPlugin

LengthAwareEDisMaxQParserPlugin

LengthAwareEDisMaxQParserPlugin は検索キーワードの文字列長を見て、「なるべくフレーズ検索が発生しないように」 edismax を呼び出すラッパーです。再現率と精度の両取りを狙った日本語検索のための形態素解析と文字N-gramを対象にしたフィールドの横断検索において、(検索応答時間という意味での)パフォーマンス向上を図ることができます。

solrconfig.xmlの設定

<queryParser name="lengthAwareEDisMax" class="com.rondhuit.solr.search.LengthAwareEDisMaxQParserPlugin">
  <lst name="qf">
    <str name="1">title_1g^5 title^10 body_1g body^2</str>
    <str name="2">title_2g^5 title^10 body_2g body^2</str>
    <str name="3">title_3g^5 title^10 body_3g body^2</str>
  </lst>
</queryParser>

LengthAwareEDisMaxQParserPlugin は edismax と同じく横断検索したいフィールド名を qf パラメータに重み付きで指定します。ただし、edismax と異なるのは、検索キーワードの長さ毎に複数指定できる点です。つまり、上記を例に取れば、検索キーワードの長さが1であればフィールド(および重み、以下同じ)title_k1^5 title^10 body_k1 body^2を対象に、検索キーワードの長さが2であればフィールドtitle_2g^5 title^10 body_2g body^2を対象に、検索キーワードの長さが3であればフィールドtitle_3g^5 title^10 body_3g body^2を対象に検索するよう、edismax クエリに展開します。では検索キーワードの長さが4以上の場合はどうなるかというと、一番近い設定、つまり上記であれば3の設定が使われます。

このようにすることで極力重い処理であるフレーズクエリの発生を抑え、検索パフォーマンスが落ちないようにしています。

検索リクエスト

検索リクエスト時は、typeに”lengthAwareEDisMax”を指定したlocalParamsを用います。

http://localhost:8983/solr/basic/select?q={!lengthAwareEDisMax}魂 日本

このとき設定が前述の通りであれば、次のようなクエリ展開がなされてedismaxが呼び出されます:

title_1g:魂^5 title:魂^10 body_1g:魂 body:魂^2 title_2g:日本^5 title:日本^10 body_2g::日本 body::日本^2

EDisMaxExQParserPlugin

辞書ベースのクエリ書き換えを行う QParserPlugin の実装です。本機能により、1行1単語のテキストファイル(辞書ファイル)を用意することで、特定のクエリを特定のフィールドに投げることができるようになります。クエリを「東京ディズニーランド」とし、辞書に「東京」が含まれている時のクエリのイメージは以下の通りです。

項目
クエリ 東京ディズニーランド
クエリ内で辞書にヒットした文字列 東京
生成されるクエリ (edismax:(東京ディズニーランド)) OR (edismax:(特定フィールド:(東京)))

設定

solrconfig.xml の設定

solrconfig.xml に記述する例を以下に記します。

<queryParser name="edismaxEx" class="com.rondhuit.solr.search.EDisMaxExQParserPlugin">
  <lst name="person">
    <str name="dic">people.txt</str>
    <bool name="remove">true</bool>
    <str name="fields">speaker^3 title</str>
  </lst>
  <lst name="location">
    <str name="dic">locations.txt</str>
    <str name="fields">statement^2 title</str>
  </lst>
</queryParser>
...
<requestHandler name="/select" class="solr.SearchHandler">
...
  <str name="defType">edismaxEx</str>
...
</requestHandler>

各属性値と要素の内容について記します。尚、lst タグの属性値と属性名は動作には直接関係しない部分です。name 属性には”location”など任意の属性値を記述して下さい。lst タグは64個まで記述することが可能です。辞書ファイル1つに対し、1つの lst タグを記述します。

dic(必須) 説明
ファイル名 辞書ファイル名のみを記述します。
remove(オプション) 説明
true 辞書に該当する文字列をクエリから削除して検索します
false(デフォルト) 辞書に該当する文字列をクエリから削除せずに検索します
fields(必須) 説明
適用フィールド 辞書にヒットしたクエリが投げられるフィールド名を記述します。フィールドは複数記述することができ、ブースト値も指定できます。
例:field_1^5.0 field_2^3.0

辞書ファイルの設定

上記 solrconfig.xml の設定で、属性値 dic に指定する辞書ファイルの内容を記します。辞書ファイルはテキストファイルとし、以下のフォーマットで記述します。

単語1
単語2
単語3
:

(例)

東京
横浜
大阪

上記のように、1行1単語で記述します。

辞書ファイルの配置

作成した辞書ファイルは、RCSS の以下のディレクトリ内に配置します。

$RCSS/LUSOLR/solr/server/resources

4. SolrPlugin の SearchComponent

CheckIndexSubsetComponent

CheckIndexSubsetComponent は fields に指定された1つ以上のフィールドに対して、検索時に fq が指定されていることを確認し、指定されていない場合は例外を発生させて検索が実行されないようにする SearchComponent です。AddFieldsFromRequestParametersUpdateRequestProcessor と組み合わせて使うことで、シングルコア環境でマルチテナントを実現するのに便利です。

solrconfig.xmlの設定

CheckIndexSubsetComponent は次のように、searchComponent を設定するところで、fq を行うフィールド名を fields パラメータで指定します。また、QueryComponent より後ろに実行されるよう、requestHandler の設定を行います。そのため、以下の例では last-components を使っています。

  <searchComponent name="checkfq" class="com.rondhuit.solr.search.CheckIndexSubsetComponent" >
    <arr name="fields">
      <str>tenant</str>
      <str>department</str>
    </arr>
  </searchComponent>

  <requestHandler name="/useCheckfq" class="org.apache.solr.handler.component.SearchHandler">
    <arr name="last-components">
      <str>checkfq</str>
    </arr>
  </requestHandler>

検索リクエスト

以上の設定の下、次のように検索を実行すると、tenant フィールドに対してテナントを絞り込む検索である fq が指定されていないので、例外が発生し検索が実行されません。

http://localhost:8983/solr/basic/useCheckfq?q=*:*&fq=department:software

次のようにテナントを絞り込む fq を指定すれば、エラーは起こらなくなります。

http://localhost:8983/solr/basic/useCheckfq?q=*:*&fq=tenant:RONDHUIT&fq=department:software

お見積もり・詳細は KandaSearch チームに
お気軽にお問い合わせください。

お問い合わせ