よしだのブログ

サブタイトルはありません。

Solr 6 新機能の紹介

https://lucene.apache.org/solr/6_0_0/images/solr.svg

だいぶ時間が立ってしまいましたが、Solr 6 がリリースされました!というわけで、Solr 6 の新機能をドキュメントから調査してみました。調査する新機能は、yonik さんの以下のエントリを参考にしました。*1

http://yonik.com/solr-6/

Parallel SQL

https://cwiki.apache.org/confluence/display/solr/Parallel+SQL+Interface#ParallelSQLInterface-JDBCDriver

  • Solr で SQL が使える (select のみ、intsert / update / delete は対応しない)
    • 裏では Presto の SQL Parser を使って Streaming Expression (こちらも新機能、後述) に変換している
  • テーブル
    • テーブル名 = コレクション名
    • case insensitive
  • カラム
    • カラム名 = フィールド名
    • case sensitive
    • エイリアスをサポート、order by クラウスで参照できる
      • は利用不可
    • カラム名に score を指定することは LIMIT クラウスが含まれる場合のみ可

例1:techproducts コレクションのフィールド、manu と price を検索する

SELECT manu as mfr, price as retail FROM techproducts
  • Aggregation Model

    • Solr の SQL では、aggregation (結果のグルーピング) を2つの方法でサポートしている
      • Solr へのリクエスト時のパラメータで、どちらを利用するかを選択できる
    • map_reduct : ワーカーノードに送信する際にシャッフル (つまりソート)を行い、ワーカーノードで aggregation を行う。GROUP BY を行う対象のフィールドのカーディナリティ (値のバリエーション) に上限はないが、検索結果全体をネットワーク上に送信するコストがかかる点に注意が必要。
    • facet : JSON Facet API / StatsComponent を利用する方法。通常の検索と同様に Solr の検索で処理させる方法なので、ネットワークに送信されるのは集約された後の結果のみ。フィールドのカーディナリティが低い場合にはとても速い。
  • 設定

    • リクエストハンドラに、/sql と /stream 、/export を設定する (いずれもデフォルトでは暗黙的に設定されているので、solrconfig に書く必要はない)
    • SQL で使用するフィールドについて、docValues を設定する
  • JDBC Driver

    • SolrJ を JDBCDriver として利用できる
  • HTTP
    • /sql に対して、SQL を POST しても利用できる

例2:HTTP による POST

-bash-4.1$ curl --data-urlencode "stmt=SELECT id, price FROM techproducts WHERE popularity=1 LIMIT 100" http://ojt02.takumyos:8983/solr/techproducts/sql?aggregationMode=facet
{"result-set":{"docs":[
{"price":19.95,"id":"F8V7067-APL-KIT"},
{"price":11.5,"id":"IW-02"},
{"EOF":true,"RESPONSE_TIME":6}]}}
  • 利用可能な表現
    • LIMIT
      • LIMIT が指定されていると score を得ることができる
      • LIMIT が指定されていると stored field なら field list に指定できる。unlimited の場合 docValues フィールドのみ利用できる
      • LIMIT が指定されていると indexed field なら order by に指定できる。unlimited の場合 docValues フィールドのみ利用できる
    • WHERE
      • = , () , OR , [ ] , NOT
    • ORDER BY
    • DISTINCT
    • Statistics
      • count / min / max / sum / avg
    • Group by
      • Having

メモ:まだ不安定な様子なので実際に利用するには程遠い

ざっと触ってみただけでも、以下の様な問題が有り、枯れていない印象です。(もしかしたら単にドキュメントが間違えているだけかもしれません・・w → Streaming Expression のドキュメントの間違いについては別のエントリにまとめます。)

  • WHERE id=apple とすると、正しくない結果が得られる (id は docvalues のフィールドではない)
  • WHERE price=[0 to 100] が利用できない (InvalidNumber エラーが出ている)
-bash-4.1$ curl --data-urlencode 'stmt=SELECT id, price FROM techproducts WHERE price="[0 to 100]" LIMIT 100' http://ojt02.takumyos:8983/solr/techproducts/sql?aggregationMode=facet
{"result-set":{"docs":[
{"EXCEPTION":"java.util.concurrent.ExecutionException: java.io.IOException: --> http://172.21.234.168:7574/solr/techproducts_shard2_replica2/:Invalid Number: ","EOF":true,"RESPONSE_TIME":7}]}}

Streaming Expressions

https://cwiki.apache.org/confluence/display/solr/Streaming+Expressions

Streaming Expression は現状、実験的な API のため将来インターフェースが変更される場合があるそうですのでご注意ください

Streaming Expression では、並行に実行される異なるタスクの結果を結合することができる機能です。

例1:Stream Expression で検索している例。

-bash-4.1$ curl --data-urlencode 'expr=search(techproducts,q="*:*",fl="price", sort="price desc")' http://ojt02.takumyos:8983/solr/techproducts/stream
  • search は export リクエストハンドラに依存しているので、sort と fl が指定されている必要がある。
  • sort に指定された項目は fl でも指定する必要がある。

指定可能な function

  • search : Solr で検索を行うファンクション、利用可能なパラメータに制限がある
  • jdbc : Stream で JDBC を使って Select を実行して結果を得る
  • facet : facet 検索を使って、バケットごとに集約する機能を提供する。
  • stats : 検索結果に対してシンプルな集約関数を提供する (sum/avg/min/max/count)
  • topics : pub/sub メッセージング。ユーザーはクエリを予め登録しておき、クエリに該当するする新規に登録されたか更新されたドキュメントを一度だけ返す。

指定可能な decorator

  • complement : クエリAとクエリBを指定し、A にはあるが Bに含まれない結果を出力する
  • daemon : 指定した間隔で繰り返しファンクションを実行する (例:あるコレクションAに対する検索結果をコレクションBに継続的に登録する、
  • innterJoin : DB の inner join に相当、右のStreamに存在する Left のデータを結合して出力する。 (2つのストリームを連結するフィールドでソートしておく必要がある)
  • intersect : Left の Stream に存在する RIght のデータを出力する。Left のデータと結合せず、Right のデータのみを出力する。(2つのストリームを連結するフィールドでソートしておく必要がある)
  • hashJoin : DB の inner join に相当、右のStreamに存在する Left のデータを結合して出力する。(2つのストリームがソートされている必要が無いが、メモリを多く利用する)
  • Merge : 2つ以上の複数の Strem を結合する。あらかじめ指定したフィールドでソートしておく必要がある。 (DBのUnion)
  • leftOuterJoin : DB の left outer join と同様に、指定した2つの結果をくっつけることができる (2つのストリームを連結するフィールドでソートしておく必要がある)
  • outerHashJoin : DB の right outer join に相当 (2つのストリームがソートされている必要が無いが、メモリを多く利用する)
  • parallel : 複数の worker ノードに指定したストリームを並列して処理させることができる
  • reduce : 共通のフィールドでグルーピングする。
  • rollup : 指定したフィールドで Steream をグルーピングし、集計を行う。 (sum / min / avg / max / count ) グルーピングするフィールドで予めソートしておく必要がある
  • select : 元のストリームに含まれるフィールドのサブセットや変更されたフィールドを出力する。(出力するフィールドのチョイス、rename、値のリプレイス)
  • top : 指定した N 件の結果を出力する。
  • unique : 指定したフィールドの値を基準にユニークなストリームを生成する
  • update : 指定したストリームを元に、インデックスの更新処理を行う。

Graph Traversal Query

https://cwiki.apache.org/confluence/display/solr/Other+Parsers#OtherParsers-GraphQueryParser

  • ファンクションクエリの一つ
  • 幅優先探索、cyclic aware (閉路をサポート?)
  • クエリパラメータの to と from に指定したフィールドの値を元に、ドキュメント間のリンクを構築する

注意:上記の cwiki のドキュメントにある、Example のグラフの絵が正しくない

制限:この機能は1つの Solr インスタンス内でしか結果をたどることが出来ません! 6.1 では Streaming Expression で複数の分散ノードでのグラフ検索がサポートされる予定です。

パラメータ

  • to : 入力エッジを示すフィールド名を指定
  • from : 出力エッジを示すフィールド名を示す
  • traversalFilter : クエリー、マッチしたノード(ドキュメント)をフィルターする条件を指定する (あるノードがマッチしなかった場合、その先のノードは探索されない)
  • maxDepth : ノードに許容されるルートノードからの距離(最大エッジ数)
  • returnRoot : ルートノードを結果に含めるかどうか (boolean)
  • returnOnlyLeaf : リーフ(incoming edge だけのノード)だけを返すかどうか (boolean)
  • useAutn : 幅優先探索のイテレーションごとにオートマトンをコンパイルするかどうかを指定する (boolean)

メモ

BM25 Scoring

  • Okapi BM25 がデフォルトになります。
  • これまでの TF-IDF を使いたい場合は、ClassicSimilarity を使ってね。

Filters for Real-Time Get

https://cwiki.apache.org/confluence/display/solr/RealTime+Get

  • Real-Time Get (リクエストハンドラー /get ) で fq をサポート。取得するドキュメントをフィルターすることができる

Cross Data Center Replication (CDCR)

https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=62687462

  • 複数のデータセンター間での、データのレプリケーション
  • active-passive シナリオのみを本バージョンではサポート
    • データの更新があった場合に、ソースとなるデータセンターから、ターゲットのデータセンター(複数)にレプリケーションする
    • その逆はない、ターゲット側で更新してもソースには反映されない
    • レプリケーション中も検索はどちらでも可能
    • ターゲットのデータセンターではデータが反映されるまでの遅延が数秒程度生じる
  • インデックスデータが disk に書き込まれてからレプリケーションは開始される (commit されてから)
  • すぐにレプリケーションを開始するか、スケジュールするかは選択することができる
  • それぞれのシャードリーダーどうしがレプリケーションを行う
  • コネクションの切断や帯域の劣化などに耐えられるように設計されている、またコミュニケーションの最適化のためにバッチアップデートもサポートする
  • 更新分のデータの一貫性は保証するが、インデックス全体の一貫性は保証しない (気にしない)
    • つまり、CDCR を開始する前にすでに登録されていたインデックスはそのまま保持される
  • コレクション単位で設定する
  • ソースの Solr クラスタからターゲットの zookeeper アンサンブルが見えるようになっている必要がある
  • 高頻度のアップデートがある環境で builk-load する用途には向いていない場合がある (帯域による) 。その場合は、あらかじめ bulk-load して同期した後に、CDCR を有効にすると良い。
  • 使用可能な帯域の指定や制限などはできないが、batch-size やスケジュールである程度コントロールできそう

メモ

  • 単純なレプリケーションだけでなくインデックスのマイグレーションに使えるかも?
    • Solr の構成が異なっても問題ないか? (シャード数、レプリカ数)
    • on the fly でレプリケーション先を指定できるか? また、解除できるか?
    • 現在登録されているデータのレプリケーションが完了したことを簡単に検知できるか? (batch update モード?)

おすすめ書籍

[改訂新版] Apache Solr入門 ~オープンソース全文検索エンジン (Software Design plus)

[改訂新版] Apache Solr入門 ~オープンソース全文検索エンジン (Software Design plus)

  • 作者: 大谷純,阿部慎一朗,大須賀稔,北野太郎,鈴木教嗣,平賀一昭,株式会社リクルートテクノロジーズ,株式会社ロンウイット
  • 出版社/メーカー: 技術評論社
  • 発売日: 2013/11/29
  • メディア: 大型本
  • この商品を含むブログ (8件) を見る

検索エンジン自作入門?手を動かしながら見渡す検索の舞台裏

検索エンジン自作入門?手を動かしながら見渡す検索の舞台裏

*1:リリースノートを見ると、ほぼ全てカバーできているみたいでしたが