mongodbから日本語で全文検索するためにElasticSearchをインストールする

mongodb での全文検索

mongodbで日本語で全文検索したい!と思ってもこれが残念ながら未だ非対応です。
参考URL
そこでElasticSearch プラグイン(MongoDB River + Kuromoji Analysis)を利用します。
ElasticSearchからプラグインを色々使ってmongodbから全文検索する感じです。

そのためにいろいろとハマったのでメモ的に書いていきます。
必要なものは以下です。

環境はCentOS 6.6 64bit です。

何度も言いますが、mongodbで日本語検索が出来れば必要ないものたちです。

mongodbのインストール

/etc/yum.repos.d/mongodb.repoを作成してリポジトリを追加する。

[mongodb]
name=MongoDB Repository
baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/
gpgcheck=0
enabled=1

mongodbをインストールします。

sudo yum install mongodb-org

mongodbの起動

sudo yum service mongod start

JDK のインストール

sudo yum install java-1.7.0-openjdk

問題はここからです。

ElasticSearchのバージョンを決める

おそらく現時点ではmongodbは2.6.8あたりだと思うのでそのつもりで各自選択していきます。

今回入れるものたちのバージョン

mongodb ElasticSearch Kuromoji Analysis Plugin MongoDB River Plugin
2.6.8 1.3.9 2.3.0 2.0.2

バージョン気にせずインストールをするとなぜか動かなかったりしますのでご注意ください。
マイナーバージョンの違いくらいだったらなんとかなるのかもしれませんが、保証はありません。
無視してやるのもいいですが、その場合は出来る限り下のバージョンにした方がいいです。
しかし、何度も言いますが、mongodbで日本語検索が出来れば必要ないものたちです。

ElasticSearch1.3.xのインストール

/etc/yum.repos.d/elasticsearch.repoを作成してリポジトリを追加します。

[elasticsearch-1.3.x]
name=Elasticsearch repository for 1.3.x packages
baseurl=http://packages.elasticsearch.org/elasticsearch/1.3/centos
gpgcheck=1
gpgkey=http://packages.elasticsearch.org/GPG-KEY-elasticsearch
enabled=1

ElasticSearchのインストール

sudo yum install elasticsearch

とりあえず起動する

sudo service elasticsearch

起動確認

curl -XGET 'localhost:9200'
{
  "status" : 200,
  "name" : "Zeitgeist",
  "version" : {
    "number" : "1.3.9",
    "build_hash" : "0915c7306e6264ba21a6cb7609b93545ccc32ef1",
    "build_timestamp" : "2015-02-19T12:34:48Z",
    "build_snapshot" : false,
    "lucene_version" : "4.9"
  },
  "tagline" : "You Know, for Search"
}

MongoDB River Plugin 2.0.2 のインストール

sudo /usr/share/elasticsearch/bin/plugin --install com.github.richardwilly98.elasticsearch/elasticsearch-river-mongodb/2.0.2

Kuromoji Analysis Plugin 2.3.0のインストール

インストール

sudo /usr/share/elasticsearch/bin/plugin --install elasticsearch/elasticsearch-analysis-kuromoji/2.3.0

/etc/elasticsearch/elasticsearch.ymlを編集

index.analysis.analyzer.default.type: custom					# 追加
index.analysis.analyzer.default.tokenizer: kuromoji_tokenizer	# 追加

ElasticSearchの再起動

sudo service elasticsearch restart

ふぅ、何度も言いますが、mongodbで日本語検索が出来れば(略

mongodbをレプリカセットで構築する

レプリカセットとは

レプリカセットとは複数のmongodbでデータの同期とサーバの冗長化を行う機能です。
MySQLのレプリケーションのようなものです。
MongoDB River Pluginを実行するために必要ですが、セカンダリを用意する必要はありません。

etc/mongod.confを編集します。

sudo vi /etc/mongod.conf 
replSet = rs01 # 最後に追記

mongodbでレプリカセットを設定する

sudo service mongod restart

mongodコンソールにて実行

mongo
config = {_id: 'rs01', members: [{_id: 0, host: 'localhost:27017'}]};
rs.initiate(config);

mongodbにデータを作ってみる

ElasticSearchにインデックスを作成

curl -XPUT 'http://localhost:9200/_river/mongodb/_meta' -d '{ 
	"type": "mongodb", 
    "mongodb": { 
      "db": "testmongo", 
      "collection": "animal"
    }, 
    "index": {
      "name": "mongoindex", 
      "type": "animal"  
    }
}'

mongoでデータを作成

mongo

use testmongo

var p = {name:"キツネ"}
db.animal.save(p)

動作を確認する

検索する日本語をUTFからURLエンコードする必要があります。
以下のサイトで変換すると「キツネ」は %e3%82%ad%e3%83%84%e3%83%8d です。

URLエンコード・デコードフォーム

日本語で検索してみる

curl -XGET 'http://localhost:9200/mongoindex/_search?q=name:%e3%82%ad%e3%83%84%e3%83%8d&pretty'

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.30685282,
    "hits" : [ {
      "_index" : "mongoindex",
      "_type" : "animal",
      "_id" : "55116bc107a66baa7b209026",
      "_score" : 0.30685282,
      "_source":{"_id":"55116bc107a66baa7b209026","name":"キツネ"}
    } ]
  }
}

※見づらいので一番後ろにprettyパラメータを入れています。

終わり

これでmongodbで日本語全文検索ができるようになりました。。。。お疲れ様です(´ω`;)

またすでにあるmongodbのデータから日本語で検索したい場合は、
ElasticSearchにインデックスを作成する際にdbとcollectionとtypeを合わせてください。

またElasticSearchのインデックスががよくわからないことになったときは
curl -XDELETE 'http://localhost:9200/*' で全部消せます。

遭遇したエラー

バージョン無視して入れていたらエラーが発生しました。

Caused by: java.lang.ClassNotFoundException: org.elasticsearch.index.analysis.kuromojitokenizer.KuromojiTokenizerTokenizerFactory
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at org.elasticsearch.common.settings.ImmutableSettings.loadClass(ImmutableSettings.java:469)
... 18 more

もうインデックスの削除コマンドすら受け付けないので、
以下のように手動でデータを消してしまいましょう。

sudo rm -r /var/lib/elasticsearch

mongodbで日本語検索が(略
mongodbでいつか日本語検索ができることを願っております(´ω`)b

参考URL

http://cohakim.com/archives/5367
https://github.com/richardwilly98/elasticsearch-river-mongodb
https://github.com/elastic/elasticsearch-analysis-kuromoji