INFORMATION
テクノロジ

Solr7 新機能について 〜Lucene/Solr Revolution 2017 より〜

著者:西潟 一生

先日リリースされた Solr7 の新機能について一部解説します。

Solr7 は 2017 年 9 月 21 日にリリースされ,2017 年 10 月 19 日時点では Solr7.1 が最新版となっています。 先日ラスベガスの Mandalay Bay で開催された Lucene/Solr Revolution 2017 では Solr7 の新機能に関するセッションが多く見受けられました。本記事ではそれをベースに Solr7 を紹介したいと思います。

Lucene/Solr Revolution 2017 の雰囲気に関しては既に弊社中山のレポート通りです。 ラスベガスに行ったら,是非グランドキャニオンには行きましょう。その目の前に広がる風光明媚な景色は言葉では言い表せません。これまでの人生で,一番写真では伝わらない景色だと感じた場所でした。

Lucene/Solr Revolution では初日と 2 日目に LucidWorks 社の Solr トレーニング(有償)を受講することが可能です。Solr トレーニングと言っても,OSS としてリリースされている Solr ではなく,それをベースにカスタマイズされている LucidWorks 社特製の Fusion という製品をベースにトレーニングが進められていきます。弊社でも Solr トレーニングを行なっていますので,トレーニング内容についてはとても気になるところですが,今回はカンファレンスのみの参加です。カンファレンスでは,当然かもしれませんが Solr 7 に関する内容が多く見受けられ,発表者もそれに関わっている方が多かった印象です。今回のカンファレンスでは私も発表者として応募し,見事に落選したのですが,新しい Solr リリースのタイミングで開催されるこのカンファレンスで発表を勝ち取るには新しい Solr の機能に関わっていないと難しいのでは?と感じた次第です。



では,Solr7 の新機能や一部 Solr のテクニックについてカンファレンスのセッションをベースにご紹介していきたいと思います。

目次

Analytics at Scale with the Analytics Component2.0

Analytics Components2.0 と呼ばれている機能の紹介です。Solr7 に標準で組み込まれており,新機能としても Feature されています。
Analytics Components は Bloomberg 社がコントリビュートした機能で,Stats Component が柔軟性に欠けたことがモチベーションだと言われています。Analytics Component1.0 リリース時は Bloomberg 社内で商用データベースの削減ができたほどだとか。本バージョンからは分散環境でも動作するようになったため,大量ドキュメントに対応でき,シャードの量に対してほぼ線形にパフォーマンスが向上するそうです。

Analytics Components2.0 の中でも Value Facets と Mapping Functions は特徴的のようです。

Value Facets は通常のファセットに加えて Mapping Expression を扱えるようにしたものらしく,従来のファセットと比べ,柔軟なファセットを構築できるようです。Mapping Expression とはファセットの値に対して変更を加えられる機能のことを指します。

以下は,まず最初に price フィールドを昇順でソートし,price フィールドの値が同じだったものに対して,その category フィールドのファセットを取ります。また category フィールドの中身が空の場合は “No Category” と出力し,それをファセットの値とする例です。(fill_missing が Mapping Expression に当たります。)

{
  type: "value",
  expression: "fill_missing(category,'No Category')",
  sort:{
    criteria :[
      {
        type:"expression",
        expression:"price",
        direction:"ascending"
      },
      {
        type:"facetValue"
      }
    ],
    limit:10,
    offset:0
  }
}

Value Facets をピボットファセットに応用してみると以下のようなことも可能です。

{
  type:"pivot",
  pivots:[
    {
      name:"category",
      expression:"fill_missing(category,'No category')",
      sort:{
        criteria:[
          {
            type:"expression",
            expression:"price",
            direction:"ascending"
          }
        ],
        limit:10
      }
    },
    {
      name:"location"
      expression:"csv(state,city)",
      sort:{
        criteria:[
          {
            type:"facetValue"
          }
        ]
      }
    }
  ]
}

これは pivots 内の要素が 2 つありますが,1 つ目の要素は前述の通りの結果です。2 つ目の要素は state と city フィールド(CSV 形式で記述)を連結したフィールドを location フィールドとするファセットを出力し,1 つ目と 2 つ目のピボットファセットを取るものです。
これで,例えば category が “Electronics(2)” というファセットは location フィールド “Austin,TX(1)” や “NYC,NY(1)” を内包する,というピボットファセットが出力されるようになります。

このように Value Facets はファセットの対象を増やしたり,ファセットになったものに対して柔軟なソートをかけられたりできます。
残念ながら,Solr7 のマニュアルにこれらの操作を行うための記述がまだ見当たらず,今は詳細を知ることができません。今回は Analytics Component2.0 を使って高度なファセットが可能になることについてご紹介しましたが,Analytics Component2.0 の機能はこれだけではありません。Solr が持つ様々な統計情報を活用し,更に深い分析が可能となっているようです。

New Replica Type for SolrCloud

このセッションでは,Solr7 で新たに追加された New Replica Type について語られていました。
Solr7 では,SolrCloud を使用する時,レプリカに形式が追加され,それぞれ以下のように名付けられました。

  • NRT Replicas
  • TLOG Replicas
  • PULL Replicas

Solr6 系まではレプリカにタイプという概念はなかったのですが,何故今回からタイプが必要になったのでしょうか?

それは,SolrCloud が GA になってからも,ユーザーはレガシーな Master/Slave 構成を取ることが多かったという事実があります。この理由の 1 つに SolrCloud が状況によっては Master/Slave 構成よりもパフォーマンス的に劣っている部分がありました。Master/Slave 構成はインデクシングとクエリが全く別々のノードに対して明示的に実行可能なので,それぞれのノードの負荷が互いに影響し合うことはありません。Slave が Master に対してレプリケーションを行う際は I/O による検索時のパフォーマンス低下はありますが,それ以外はそれぞれがベストなパフォーマンスを発揮できていました。しかしながら SolrCloud では,ここまで明示的に負荷が分散することはありませんでした。

この理由には,シャードに対するレプリカの数だけコミットとマージが走ることが挙げられます。例えば,3 シャードあれば,3 レプリカに対してアップデートやインデクシングが実施されます。この数ならまだ良いですが,100 シャードとなればそのコストはとても無駄です。

SolrCloud ではドキュメントをポストする先が 1 つの Solr のように見えることから,内部的にはポストされたドキュメントは適切なノードに配置されるようにフォワードされます。フォワードされた先で tlog の作成やドキュメントのインデクシングがそれぞれ行われるため,Master/Slave 構成のようにインデクシング担当,クエリ担当と言った明確な分け方ができていなかったことが課題でした。

Solr7 では上記の問題を解決するため,3 つのレプリカタイプを用意しました。このタイプはレプリカを作成する際に指定できます。詳細については後述します。
以下にそれぞれ簡単に役割を解説していきます。

NRT Replicas

Solr6 系までは全てのこのレプリカタイプのみでした。Solr7 系以降もデフォルトはこのレプリカタイプが適用されます。
名前にあるようにソフトコミット(NRT)ができるのはこのレプリカタイプのみです。他の 2 つのレプリカタイプでは NRT は実現できないので,NRT が要件にある時点で,このレプリカタイプは必須となります。同様にリアルタイムゲットができるのもこのレプリカタイプだけです。

TLOG Replicas

tlog のアップデートはするが,インデクシングはしない,というレプリカタイプです。tlog とは Solr にポストされるドキュメントの文字列情報が記述されているファイルで,このファイルがあればオリジナルのドキュメントがなくても再インデクシング(リプレイと呼ばれます)が可能となります。Solr ではインデクシングする際に,このファイルの生成も同時に行なっています。
インデクシングはしないので,そのコストは大幅に削減できます。このレプリカタイプはリーダーから定期的にセグメントファイルのコピーは行われることから,検索はこのセグメントファイルがコピーされた時点で有効になります。この動きは Master/Slave 構成の Slave と同様です。TLOG Replicas はレプリカだけでなく,リーダーにも成ることが可能です。リーダーになった際は NRT Replicas と同じ役割を果たします。NRT Replicas とは異なりソフトコミット,リアルタイムゲットはできません。

PULL Replicas

tlog のアップデートすら行わず,セグメントファイルのコピーだけが行われるレプリカタイプです。リードオンリーの検索専用レプリカと言ったイメージでしょうか。TLOG Replicas と同様にソフトコミット,リアルタイムゲットはできません。リーダーになることもできません。

以上 3 つのレプリカタイプには推奨される組み合わせがあります。以下の 3 つが推奨されています。

  • 全て NRT Replicas
  • デフォルト設定です。(Solr6 系以前の構成)
    ソフトコミットをしたい場合はこの組み合わせしかありません。
    小 〜 中サイズのクラスター,もしくは 弱 〜 中 のインデクシングスループットの時にこの構成を取ると良いとされています。
  • 全て TLOG Replicas
  • NRT が必要なく,インデクシングのスループットが高い時にはこの構成を取ります。
    中 〜 大 サイズのクラスターであるが,全てのレプリカに tlog を持たせたい時はこの構成を取ると良いとされています。
  • TLOG Replicas + PULL Replicas
  • 全て TLOG Replicas の時の特徴に加え,インデクシング時にも高い検索性能を出したい時にはこの構成を取ると良いとされています。

使い方は簡単です。コレクションを作る時,またはレプリカを追加する時に,以下のように TLOG Replicas はこのシャード名である,と言った指定をするだけです。

create...&tlogReplicas=shard1&pullReplicas=shard2&pullReplicas=shard3

Autoscaling Solr

Solr7 系から Autoscaling に関する機能が追加されました。この機能を使うことで,自動でレプリカを追加したり,各 Solr ノードのコア数や負荷が均等になるようなノードの配置が可能になり,常に理想的なクラスターを維持できるようになります。 理想的なクラスターとは以下のようなクラスターを指します。

  • 自動でクラスターのバランスを取ること
  • 安定的で一定以上の性能が出ていること
  • 常にディスクに余裕があること
これを実現するために以下のような情報を Solr が取得し理想的なクラスターを維持するようにします。
  • 各ノードの負荷の平均
  • 空きディスク容量
  • ヒープの使用状況
  • Solr コアの数
これらの情報によって例えば,「1 ノード 1 レプリカで必ず空きディスクが 100GB ある状態」と言ったようなことを自動で維持できるようになります。

Autoscaling を利用するには以下の 2 つを設定する必要があります。

  • Preferences
  • Policy

Preferences

Preferences はクラスタ全体に関する設定を行います。例えば {“minimize”:”cores”} と設定した時,各ノードのコア数を最小化する挙動となります。
{“maximize”:”freedisk”, “precision”:”50″} とした場合は,ディスクの空きが 50GB になったら別ノードにレプリカが作成される挙動となります。

Preferences の API は以下のように使用します。(V2 API フォーマットの場合)

#API の例
curl -X POST http://host:port/v2/cluster/autoscaling -d
{
  "set-cluster-preferences": [
    {"minimize": "cores"},
    {"maximize": "freedisk", "precision":"100"}
  ]
}

Policy

Policy はノードがクラスターに参加する際の設定を行います。
{“node:#ANY”, “cores”:”<6"} と設定した時,全てのノードのコア数を 6 未満にする挙動となります。
{“node:#ANY”, “collection:collection1”, “shard”:”#EACH”, “replica”:”<2"} と設定した時,collection1 というコレクションは,1 シャード 1 レプリカの状態にし,それぞれ別ノードに配置される挙動となります。

Policy の API は以下のように使用します。(V2 API フォーマットの場合)

curl -X POST http://host:port/v2/cluster/autoscaling -d
{
  "set-cluster-policy" : [
    {"node":"#ANY", "cores": "<6"},
    {"node":"#ANY", "replica": "<2", "shard": "#EACH"}
  ]
}

その他にも以下のリクエストで各ノードの負荷状態を取得することができたり

curl -X POST http://host:port/v2/cluster/autoscaling/diagnostics
以下のリクエストで Preferences や Policy の一覧を取得することができます。
curl http://host:port/solr/admin/metrics

Autoscaling Triggers

Autoscaling Triggers はノードを追加,削除した時に発動される機能のことです。発動時に以下を実行できます。

  • Compute Plan
  • 現状の Preferences/policy を評価する。
    Preferences/Policy に合う状態のリストを作成する。
  • Execute Plan
  • Compute Plan で作成したリストを実行する。

Trigger Listeners

Trigger Listeners は Trigger にアタッチされ,ライフサイクルイベントを通知する仕組みです。
ライフサイクルとは Trigger の起動から停止,成功,失敗など個々のアクションの開始から終了までを含みます。これらのアクションは自動で保存され,別システムに HTTP に送信する仕組みを持ちます。

AutoAddReplicas

Solr7.1 から導入された機能です。以前より SolrCloud では “autoAddReplicas” をサポートしてきましたが,これは Shared file system(HDFS) のみで有効でした。
通常のファイルシステムでもこの機能が使えるようになったため,Autoscaling などの機能と合わせて使うことで,より可用性が高いクラスターを構築できます。 レプリカの自動追加に加え “AutoSplitShard” については必要であることは認識しているようで,将来的には実装されるかもしれないとのことでした。

Doing synonyms right

Solr7 の新機能ではありませんが,シノニムの運用についてのセッションがあったのでご紹介したいと思います。

Solr6.4 からシノニムのデフォルト設定は SynonymGraphFilter になっています。(SynonymFilter は Deprecated になりました)SynonymGraphFilter は SynonymFilter に比べて少しパフォーマンスが劣化するのですが,SynonymFilter にあった Multi-word Synonyms 問題が解消されているので,この問題に該当する場合は有用です。この件については[この記事]でも触れていますので,そちらも合わせてご覧下さい。

この問題は,シノニムに複数単語を記述した時に発生します。例えばインデックス側にシノニムを定義した際には以下のような問題が発生します。

synonyms.txt: US, United States
文書: US sales increased
トークン:
US(1) | United(1) | sales(2) | states(2) | increased(3)
ヒットするクエリ: "United sales"
ヒットしないクエリ: "United States sales"
SynonymFilter の場合は以上のようなトークンの展開となり,本来ヒットして欲しいはずのフレーズ “United States sales” がヒットしません。(sales(3)となっている必要があります)逆にヒットして欲しくないフレーズ “United sales” がヒットする問題がありました。
では,クエリ側に設定した場合はどうでしょうか?
synonyms.txt: US, United States
クエリ: "US sales"
クエリ式:"(US United)(sales states)"
ヒットするクエリ: "US sales", "United sales", "US states"
クエリ側に設定した場合もインデックス側とほぼ同様の状況になります。”US sales” が当たるのは問題ないのですが,”US sales” で “United sales” や “US states” がヒットするのは問題です。
これらの問題が解決されたのが SynonymGraphFilter です。

実は少しトリッキーですが Solr6.4 以下をお使いの方(SynonymFilterをお使いの方)でも上記の問題を回避する方法があります。
それは “expand=false” にしたシノニムをインデックス,クエリ両方に設定する方法です。ちなみに,”expand=false” にすると,シノニムの記述が A,B,C であった時 B と C は A に寄せられるという挙動でした。

# managed-shcema
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
  <analyzer type="index">
    ...
    <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="false"/>
    ...
  </analyzer>
  <analyzer type="query">
    ...
    <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="false"/>
    ...
  </analyzer>
</fieldType>
この設定にし,且つシノニム定義ファイルには,例えば以下のように記述します。
# synonyms.txt
TID://109487252, US
TID://109487252, United States
1 カラム目の記述はユニークな文字列であれば何でも構いません。
この記述では「US」と「United States」は「TID://109487252」という文字列に寄せられることになります。 この設定により,全てのシノニムが 1 トークン(例では”TID://109487252″)になることで,Multi-word Synonyms 問題が解消されます。

実はまだ少し問題があります。クエリ側のみにシノニムを設定した場合,レアなシノニムが出現している文書のスコアが高くなってしまうという問題です。
例えば,以下の 5 つの文書があったとします。

  • doc1: US these days
  • doc2: About the US
  • doc3: US postal service
  • doc4: US government
  • doc5: Employment in United States
この時,クエリを “US” とすると,クエリは “US,United States” と展開され,doc1 〜 doc5 がヒットします。ここまでは良いのですが,doc5 に出現している “United States” はユニークなので IDF 値が高くなり,結果,スコアが不当に高くなってしまいます。 クエリ側に設定することでこのようなスコアの問題が発生してしまう可能性があるため,それを回避したい場合は上記のようにインデックス側とクエリ側にシノニムの設定をします。そのままインデックス側とクエリ側に設定しても良いですが 上記のトリッキーな方法を使えばインデックスサイズは更に小さくなることが期待できます。

総括

簡単ですが,Solr7 の新機能である,Analytics Component2.0,レプリカタイプ,Autoscaling をご紹介しました。

今回の Solr のメジャーアップデートも Solr の可用性を増すアップデートが多かったように見受けられます。Autoscaling は先日リリースされた 7.1 で色々と機能が増えていますので,是非 7.1 以降をお使い下さい。

また,シノニムの運用についても少し触れてみました。Lucene/Solr Revolution ではこのような設定テクニックレベルのセッションがちらほらと開かれています。本カンファレンスは中〜上級者向けかと思われる方もいるかもしれませんが,初級者にとっても非常に有用なカンファレンスです。 ロンウイットでは近々 Solr7 に対応したトレーニングも開催予定です。ご興味のある方は是非弊社トレーニングの受講をご検討下さい。


KandaSearch

KandaSearch はクラウド型企業向け検索エンジンサービスです。
オープンAPIでカスタマイズが自由にできます。

  • セマンティックサーチ

    人間が理解するように検索エンジンがテキストや画像を理解して検索できます。

  • クローラー

    検索対象文書を収集するWebクローラーが使えます。

  • 簡単操作のUIと豊富なライブラリー

    検索や辞書UIに加え、定義済み専門用語辞書/類義語辞書やプラグインがあります。

  • ローコードで低コスト導入

    検索UIで使い勝手を調整した後、Webアプリケーションを自動生成できます。

セミナー

企業が検索エンジンを選定する際のポイントから、
実際の導入デモをお客様ご自身でご体験!