2011年08月03日

SolrのEmbeddedSolrServerからIndexSearcherを使ってみる

Solrの勉強がてらにEmbeddedSolrServerから直接IndexSearcherを奪って処理をさせてみた。コードはScala。

こんな使い方をして良いのかと聞かれると、どう見ても良くはない。こんな方向性の勉強で良いのかと言われると、これまたどう考えても良くはない。でも、楽しかったから良しとする。



やったことは、EmbeddedSolrServerを継承したクラスでSolrCoreを取れるようにして、CoreからIndexSearcherを取り出した。

更新処理が被らない前提で手元のインデックスに対して手早く大量の処理させるという用途では、それなりに上出来な動きをしてくれた。

でも、挙動はかなり危ういので、次に書く時はちゃんとSolrの仕組みに沿った書き方をしようと思う。。。

/** EmbeddedSolrServerを継承したクラス */
class MyEmbeddedSolrServer(container: CoreContainer, coreName: String)
extends solrj.embedded.EmbeddedSolrServer(container: CoreContainer, coreName: String) {

def this(solrHomePath: String, solrXmlPath: String, coreName: String) = {
this(SolrHelper.getContainer(solrHomePath, solrXmlPath, coreName), coreName)
}

def this(solrXmlPath: String, coreName: String) = {
this(SolrHelper.getContainer(solrXmlPath, coreName), coreName)
}

/** これでCoreを取る */
def getCore() = coreContainer.getCore(coreName)

/** 最後に必ずshutdownする(しないと処理が終わらなくなる) */
def shutdown() = coreContainer.shutdown
}

/** 上のクラスを使ってみる */
val server = new MyEmbeddedSolrServer("solr-3.2/server/solr/solr.xml", "coreName")

// coreは呼び出したら必ず閉じること(閉じないと処理が終わらなくなる)
val core = server.getCore()
val ref = core.getSearcher()
try {
// これでSolrIndexSearcher(IndexSearcherを継承)が取れる
val searcher = ref.get

// SolrのTrieDateFieldに対してRangeで検索してみた
val query = NumericRangeQuery.newLongRange("createdAt", 64, new Date().getTime - 3600 * 1000, new Date().getTime, false, false)
val topDocs = searcher.search(query, 10000000)

topDocs.scoreDocs foreach (scoreDoc => {
val doc = searcher.doc(scoreDoc.doc)
// なんか処理
})

} finally {
ref.decref()
core.close()
server.shutdown()
}


decrefとかcloseとかshutdownとかいろいろ後処理が必要で、その辺の処理を誤るとJVMが立ち上がりっぱなしになってしまうという非常に危ういソース。

EmbeddedSolrServerの動きはまだイマイチ把握しきれてない。暇な時にもうちょっと奥までソースを読んでおきたいところ。今後もいろいろ変更が発生しそうなところではあるけど。