SolrのTokenFilterを書いてみる(Scalaで)

Solrのフィルタやらを書けるようになっておきたいよねー、でもJavaは色々面倒なので最近はできれば直接は触りたくないよねー、ということでScalaで書いてみた。Solrの拡張は全然わかってないので色々間違っているかもしれないけれども。サンプルとして書いたコードは、とりあえずGitHubにアップしておいた

Step1. build.sbtを作成

今回はこんな感じで書いてみた。

name := "sample filters"
 
organization := "com.github.tarhashi"

version := "0.1"

scalaVersion := "2.9.1"

libraryDependencies ++= Seq(
    "org.apache.lucene" % "lucene-core" % "3.6.0"
    , "org.apache.solr" % "solr-core" % "3.6.0"
)

Step2. TokenFilterFactory, TokenFilterを実装

TokenFilterFactoryはorg.apache.solr.analysis.TokenFilterFactoryインタフェースを実装する必要がある。特に凝ったことをしなくてもいいときはorg.apache.solr.analysis.BaseTokenFilterFactoryを継承して作成すれば最小限のコードでよさそう。Scalaで書くとこんな感じ。

package com.github.tarhashi.solr.sample

import org.apache.lucene.analysis.TokenStream
import org.apache.solr.analysis.BaseTokenFilterFactory
import org.apache.solr.analysis.TokenFilterFactory

import com.github.tarhashi.lucene.sample.SampleFilter

class SampleFilterFactory extends BaseTokenFilterFactory {
  
  override def create(input: TokenStream) : TokenStream = {
    new SampleFilter(input)
  }

}

次に、org.apache.lucene.analysis.TokenFilterを継承してTokenFilterの実体を作成。試しに、term textのひらがなをカタカナに置き換えるような処理を書いてみた。

package com.github.tarhashi.lucene.sample

import org.apache.lucene.analysis.TokenFilter
import org.apache.lucene.analysis.TokenStream
import scala.collection.mutable.ArrayBuffer
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute
import org.apache.lucene.analysis.ja.tokenattributes.ReadingAttribute

class SampleFilter(input: TokenStream) extends TokenFilter(input) {
  
  private val termAttr = addAttribute(classOf[CharTermAttribute]);
  private val readingAttr = addAttribute(classOf[ReadingAttribute]);
  
  def incrementToken(): Boolean = { 
    if (input.incrementToken) {
      val str = termAttr.toString
      termAttr.setEmpty.append(convertHiraganaToKatakana(str))
      true
    } else {
      false 
    }
  }
  
  /**
   * ひらがなをカタカナに変換する
   */
  private def convertHiraganaToKatakana(str:String):String = {
    var sb = new StringBuilder
    val map = (('ぁ' to 'ん').zip(('ァ' to 'ン'))).toMap
    for(c

Step3. jarファイルを作成

sbtでjarファイルを作成。

$ sbt package
...
[info] Packaging /home/masaki/projects/solr-filter/target/scala-2.9.1/sample-filters_2.9.1-0.1.jar ...
[info] Done packaging.
[success] Total time: 19 s, completed 2012/07/08 21:28:01

Step4. jarファイルを配置

作成したフィルタをexampleのtext_jaに組み込むために、まずはjarファイルを配置。多分scalaのライブラリのjarファイルも参照できないといけないのでそれも配置。

$ mkdir -p /path/to/solr/example/solr/lib
$ cp target/scala-2.9.1/sample-filters_2.9.1-0.1.jar /path/to/solr/example/solr/lib
$ cp /path/to/scala-library.jar /path/to/solr/example/solr/lib

Step5. 設定ファイルに追加

まずは配置したjarファイルが見つけられるように設定を追加。

$ cd /path/to/solr/example
$ vi solr/conf/solrconfig.xml
# 他のlibの設定のあたりに/path/to/solr/example/solr/libの設定を追加
<lib dir="/home/masaki/projects/apache-solr-3.6.0/example/solr/lib" />

次に、text_jaに組み込み。

vi solr/conf/schema.xml
# fieldType text_jaの一番下に以下を追加
<filter class="com.github.tarhashi.solr.sample.SampleFilterFactory" />

Step6. Solr起動

$ java -jar start.jar

エラーなく起動したら、http://localhost:8983/solr/admin/analysis.jsp から試してみる。なんとなく動いてそう。最初設定が間違っていてうまく動いてくれなかったけど、結果的にはかなり簡単な設定で動いてくれた。