Lucene久々に、書いてみたくなっただけのエントリ。Directory実装を使って、遊びます。VM間でクラスタを構成し、比較的簡単にデータを共有することができます。LuceneのDirectoryを実装した機能があります。Searchでインデックスの保存先にInfinispanを選んだ時にクラスタ構成時にインデックスを複数Nodeで共有できるのは、Infinispanにこの機能があるからですね。Directoryを使って、こういうものを作って遊んでみます。インデックスに対して、インタラクティブにDocumentを登録できるIndexerを作るインデックスに対して、インタラクティブにQueryを発行できるSearcherを作るこれらのプログラムをInfinispanのクラスタとして構成し、Indexerで登録したDocumentがSearcherから見えることを確認するInfinispanクラスタ上のNodeについては基本的に各々の役割みたいなものは気にしませんが、今回はプログラムの特性上こんな形にします。インデックスの分散保持であり、分散検索ではありませんのでご注意を。更新についても通常のLuceneと同様、IndexWriterは(Infinispanの場合、クラスタ上で)ひとつしかオープンすることができません。プログラムは、Scalaで書きます。準備まずは、sbtの設定。"4.10.3")Infinispanは、7.1.1.Finalを使用します。これに対応するLucenenは、4.10.3となります。7.2になれば、4.10.4になるみたいです。設定ファイルクラスタを構成するので、InfinispanとJGroupsの設定ファイルを用意します。Infinispanの設定ファイル。</cache-container></infinispan>Cacheは、3つ定義しており、それぞれ以下の用途と定義となっています。インデックスのメタデータを登録するCache。インデックスの実データを持つCache。Luceneのロックに使うCache。Cacheも有効にしてみました。JGroupsの設定ファイルは、こちら。小さめな設定にしています。ClassIndexerとSearcherのために、ちょっとした簡易なトレイトなどを用意しました。ログというか、コンソール表示用のトレイト。println(msg)}どのNodeか分かるように、Node名を取るようにしています。Class)を仕込みます。}}これで、LifecycleやAutoCloseableなリソースを、foreachで閉じることができるようになりました。それでは、メインのプログラムへ。Indexerそれでは、インデックスにDocumentを登録する方のプログラム。コンソールで受け取った文字列を、そのままLuceneのDocumentとして登録します。DocumentのFieldはひとつとします。}}こちらは、割と小さめです。start、indexingWhileメソッドの中は、後述します。ここで、Infinispanのクラスタを構成するNode、Cacheを起動してLuceneのDirectoryを作成します。}ここでは、Infinispanのクラスタ構成要素となるDefaultCacheManagerを作成し(Nodeみたいなもの)、そこから先ほどの設定ファイル(infinispan.xml)で定義したCacheを取得します。これら3つのCacheを使ってインデックス名を指定しつつ、LuceneのDirectoryをDirectoryBuilderを使って作成します。チャンクサイズは、デフォルトが3kですが少し大きくしておきました。今回のプログラムでは、大した意味はありませんが。続いて、Documentを登録する部分。Directoryを使ったプログラミングになります。微妙なのは、最初に何かDirectory内にデータができるようなことをしておかないと、空のインデックスを開こうとしてSearcherが失敗するため、とりあえずIndexWriterをコミットしています。あとは、コンソールから入力した文字列をDocumentのフィールドとして登録します。これを繰り返し、「exit」と入力されるとプログラムは終了します。Searcherそして、インデックスに対して検索を行う側のプログラム。コンソールからLuceneのQueryParserで解釈可能なクエリを文字列として受け取り、そこからLuceneのQueryを作って結果を表示します。}}Searcher側は複数起動することを想定しているので、仮のNode名を引数で受け取ることにしました(ただのコンソール表示用です)。Searcher(args(0)).start()こちらも、実際の処理を開始するstartメソッドから。}ここは、インデックスを作成する側とそう変わりません。検索の中核は、queryWhileというメソッドなのですが、先に部品から。文字列として入力されたクエリをパースするメソッド。}パースに失敗してもいいように、Tryで包んでいます。続いて、IndexSearcherとパースされたQueryを使って検索を行うメソッド。こちらは、ヒット件数とScoreDocの配列を戻します。}これらを使って、インタラクティブにクエリを受け付けるメソッドはこうなりました。}Indexerと同じく、こちらも「exit」と入力されると終了します。プログラムがScalaで書かれていることを除いては、普通のLuceneを使ったコードだと思います。動作確認それでは、動かしてみましょう。Indexerは、IndexWriterを開きっぱなしなこともあるのと、登録する役割は複数いらないので、ひとつのNodeとします。Indexerが登録したDocumentが検索できることと、いきなり3つ全部起動しても面白くないので最後のひとつは別のタイミングで起動することにします。Indexerを起動。org.littlewings.infinispan.lucene.Indexer'起動すると、こんな感じで入力待ちになります。prompt.addDocument>続いて、Searcherを起動。S2'メンバーがクラスタに増えたことを検知すると、増えるにしたがってこんな感じのログがコンソールに出力されます。Searcher側は、こんな感じで入力待ちになります。prompt.S2:Query>では、IndexerでDocumentを登録。added.これを、Searcher側で検索することができます。あなたとJAVA、今すぐダウンロード!!どちらのNodeからも、登録したDocumentが見えています。クラスタに参加した時に、データがNode間で共有されたからですね。IndexerでDocumentを追加。added.この追加分も、検索できます。Clojureさらに、Node追加。Node存在することになります。xxxxx-9514]この追加されたNodeからも、検索を行うことができます。Directory実装を使って、Node間でインデックスを共有して遊んでみました。久々にこのコードを書きましたが、やっぱり複数プロセスでクラスタを組む形にするとそこそこ大変...。VMプロセス内で簡易にクラスタを組んで遊んでいることが多いので。個人的にはScala、Infinispan、Luceneと趣味ド真ん中の内容なので、意外と楽しかったりします。今回作成したコードは、こちらに置いています。読者になる検索リンクはてなブログブログをはじめる週刊はてなブログはてなブログPro月別アーカイブはてなブログをはじめよう!Kazuhiraさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。