最近、Apache Solrを触る機会があったので、個人的にもいじってみています。
PostgresのデータベースのコンテンツをSolrに流し込む必要があったのですが、Solr5でのPostgresとの連携については日本語文献が見当たらなかったので、やってみたメモを残しておきます。
Solr5になってから設定ファイル周りが結構変わっており、少し手間取りました。。
1. 環境
- CentOS 6.6 (32bit)
- Oracle JDK 8 Update 65
- Apache Solr 5.3.1
- postgresql-server 8.4.20-4.el6_7
2. Solrのインストール
ApacheのページからSolrのバイナリを環境に持っていきます。
このとき、ソースコードも一緒にダウンロードしておくと、エラーが出て詰まったときにサクっと調べられます。(解決できるかどうかは別問題だけど)
バイナリを展開。
使ってみる。
Solr Quick Startで案内されている方法だと、クラスタ構成(SolrCloud)で起動されます。
$ bin/solr start -e cloud -noprompt
Welcome to the SolrCloud example!
--- (snip) ---
停止。
$ bin/solr stop -all ; rm -Rf example/cloud/
今回はクラスタ構成でなくシンプルに立ち上げます。
3. Postgresのインストール
Solr + PostgreSQL連携(Solr4.9)で紹介されている方法をそのまま使わせていただきました。
Postgresをインストールします。
# yum install postgresql-server
Postgresを立ち上げます。
$ sudo service postgresql initdb
[sudo] password for hashiwa:
データベースを初期化中: [ OK ]
$ sudo service postgresql start
postgresql サービスを開始中: [ OK ]
Solrから接続するユーザーを作成します。(スーパーユーザーじゃないほうが良かったかも)
$ sudo su - postgres
-bash-4.1$ createuser solruser
新しいロールをスーパーユーザとしますか? (y/n)y
-bash-4.1$ createdb postdb -O solruser
パスワードを設定します。
-bash-4.1$ psql
psql (8.4.20)
"help" でヘルプを表示します.
postgres=# alter user solruser encrypted password 'solrpassword';
ALTER ROLE
postgres=# alter user postgres encrypted password 'postgrespassword';
ALTER ROLE
postgres-# \q
認証METHODをmd5に変更します。
$ vim /var/lib/pgsql/data/pg_hba.conf
67 # TYPE DATABASE USER CIDR-ADDRESS METHOD
68
69 # "local" is for Unix domain socket connections only
70 local all all md5
71 # IPv4 local connections:
72 host all all 127.0.0.1/32 md5
73 # IPv6 local connections:
74 host all all ::1/128 md5
Postgresサービスを再起動します。
# service postgresql restart
postgresql サービスを停止中: [ OK ]
postgresql サービスを開始中: [ OK ]
forumテーブルを作成します。
$ psql -U solruser -d postdb
ユーザ solruser のパスワード:
psql (8.4.20)
"help" でヘルプを表示します.
postdb=# create table forum (
postdb(# id serial primary key,
postdb(# name varchar(32),
postdb(# body varchar(1024),
postdb(# updated timestamp(0) not null default current_timestamp);
NOTICE: CREATE TABLEはシリアル列"forum.id"用に暗黙的なシーケンス"forum_id_seq"を作成します。
NOTICE: CREATE TABLE / PRIMARY KEYはテーブル"forum"に暗黙的なインデックス"forum_pkey"を作成します
CREATE TABLE
差分インポート用の関数とトリガーを定義します。
postdb=# CREATE LANGUAGE plpgsql;
CREATE LANGUAGE
postdb=# create function set_update_time() returns opaque as '
postdb'# begin
postdb'# new.updated := ''now'';
postdb'# return new;
postdb'# end;
postdb'# ' language 'plpgsql';
CREATE FUNCTION
postdb=# create trigger update_tri before update on forum for each row
postdb=# execute procedure set_update_time();
このとき、テーブルは以下の状態です。
postdb=# \d forum
テーブル "public.forum"
カラム | 型 | 修飾語
---------+--------------------------------+-------------------------------------------------------
id | integer | not null デフォルト nextval('forum_id_seq'::regclass)
name | character varying(32) |
body | character varying(1024) |
updated | timestamp(0) without time zone | not null デフォルト now()
インデックス:
"forum_pkey" PRIMARY KEY, btree (id)
トリガ:
update_tri BEFORE UPDATE ON forum FOR EACH ROW EXECUTE PROCEDURE set_update_time()
Solrから検索されるデータを3つ挿入しておきます。
postdb=# insert into forum (name, body) values ('Bobbie Waterbury', 'Daddy!My Daddy!');
INSERT 0 1
postdb=# insert into forum (name, body) values ('James Bond', 'Do I look like I give a damn?');
INSERT 0 1
postdb=# insert into forum (name, body) values ('Andy Dufresne', 'Get busy living, or get busy dying.');
INSERT 0 1
データは以下のように挿入されました。
$ psql -h localhost -U solruser -d postdb -t -c 'select * from forum;';
ユーザ solruser のパスワード:
1 | Bobbie Waterbury | Daddy!My Daddy! | 2015-12-26 18:02:10
2 | James Bond | Do I look like I give a damn? | 2015-12-26 18:02:18
3 | Andy Dufresne | Get busy living, or get busy dying. | 2015-12-26 18:02:28
4. JDBCのダウンロード
Postgres用のJDBCをダウンロードしておきます。
$ curl https://jdbc.postgresql.org/download/postgresql-9.4.1207.jre6.jar > postgresql-9.4.1207.jre6.jar
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 593k 100 593k 0 0 93681 0 0:00:06 0:00:06 --:--:-- 129k
5. Solrの設定
Solrの設定も、Solr + PostgreSQL連携(Solr4.9)をかなり参考にさせていただきました。ただ、Solr5になったことで注意が必要なところがあります。
念のため、サーバーディレクトリをコピーして、そちらを使用します。
サーバーディレクトリは、デフォルトだとserverディレクトリとなっているので、serverディレクトリを任意のディレクトリ名でコピーします。
$ cp -r server/ hsw_server
今回は、デフォルトで用意されているコレクションであるcollection1を使用します。1
コピーしたサーバーディレクトリの、collection1のsolrconfig.xmlを編集します。
ライブラリの設定。
<lib dir="/home/hashiwa/solr/solr-5.3.1-bin/hsw_server/lib/" regex="postgresql-\d.*\.jar" />
<lib dir="/home/hashiwa/solr/solr-5.3.1-bin/dist/" regex="solr-dataimporthandler-\d.*\.jar" />
<lib dir="/home/hashiwa/solr/solr-5.3.1-bin/contrib/dataimporthandler-extras/lib/" regex=".*\.jar" />
また、Solr5ではデフォルトではスキーマレスモードになっており、schema.xmlでスキーマを指定できないようです。
RESTでスキーマを追加することもできるようですが、スキルがないのでクラシックなschema.xmlでの指定を使うことにします。
SchemaFactoryの変更。
<!--
<schemaFactory class="ManagedIndexSchemaFactory">
<bool name="mutable">true</bool>
<str name="managedSchemaResourceName">managed-schema</str>
</schemaFactory>
-->
<schemaFactory class="ClassicIndexSchemaFactory"/>
AddSchemaFieldsUpdateProcessorFactoryの設定の削除。
<!--
<processor class="solr.AddSchemaFieldsUpdateProcessorFactory">
<str name="defaultFieldType">strings</str>
<lst name="typeMapping">
<str name="valueClass">java.lang.Boolean</str>
<str name="fieldType">booleans</str>
</lst>
<lst name="typeMapping">
<str name="valueClass">java.util.Date</str>
<str name="fieldType">tdates</str>
</lst>
<lst name="typeMapping">
<str name="valueClass">java.lang.Long</str>
<str name="valueClass">java.lang.Integer</str>
<str name="fieldType">tlongs</str>
</lst>
<lst name="typeMapping">
<str name="valueClass">java.lang.Number</str>
<str name="fieldType">tdoubles</str>
</lst>
</processor>
-->
リクエストハンドラの設定。
これはData Import Handlerという機能を使うための設定で、設定自体はdataconfig.xmlに記載します。
<requestHandler name="/dataimport-hswtest" class="org.apache.solr.handler.dataimport.DataImportHandler" >
<lst name="defaults">
<str name="config">dataconfig.xml</str>
</lst>
</requestHandler>
dataconfig.xmlの設定。
Postgresで設定したユーザーやらパスワードやらテーブルやらを設定します。
<dataConfig>
<dataSource name="ratings"
driver="org.postgresql.Driver"
url="jdbc:postgresql://localhost:5432/postdb"
user="solruser"
password="solrpassword" />
<document>
<entity name="forum"
query="select * from forum"
deltaQuery="select id from forum where updated >= '${dataimporter.last_index_time}'"
deltaImportQuery="select * from forum where id=${dataimporter.delta.id}">
<field column="id" name="id" />
<field column="name" name="name" />
<field column="body" name="body" />
<field column="updated" name="updated" />
</entity>
</document>
</dataConfig>
また、忘れずにJDBCのjarもsolrconfig.xmlで指定した場所に置いておく必要があります。
$ cp postgresql-9.4.1207.jre6.jar /home/hashiwa/solr/solr-5.3.1-bin/hsw_server/lib/
schema.xmlを作成します。
<?xml version="1.0" encoding="UTF-8" ?>
<schema name="hsw-example" version="1.5">
<field name="id" type="string" indexed="true" stored="true" required="true" />
<field name="name" type="text_en" indexed="true" stored="true" termVectors="true" termPositions="true" />
<field name="body" type="text_en" indexed="true" stored="true" termVectors="true" termPositions="true" />
<field name="updated" type="timestamp" indexed="true" stored="true" termVectors="true" termPositions="true" />
<field name="_version_" type="long" indexed="true" stored="true"/>
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
<fieldType name="string" class="solr.StrField" sortMissingLast="true" />
<fieldType name="timestamp" class="solr.TrieDateField" />
<fieldType name="text_en" class="solr.TextField">
<analyzer>
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.StopFilterFactory" ignoreCase="true" words="lang/stopwords_en.txt" />
</analyzer>
</fieldType>
<uniqueKey>id</uniqueKey>
<!-- depricated
<defaultSearchField>body</defaultSearchField>
<solrQueryParser defaultOperator="AND" />
-->
</schema>
注意点:
- solr.LongFieldがなくなっているらしく、solr.TrieLongFieldにする必要がある
- idをlongにすると、elevate.xmlでid=MA147LL/Aとしているからかエラーになるため、stringにする
6. Solrの起動・データインポート
いよいよSolrを触っていきます。
Solrを起動。このとき、設定したサーバーディレクトリを指定する必要があります。
$ bin/solr start -d hsw_server/
Waiting up to 30 seconds to see Solr running on port 8983 [/]
Started Solr server on port 8983 (pid=20468). Happy searching!
Solrのコンソール( http://localhost:8983/solr/ )にアクセス。
[Core Selector]からcollection1を選択し、[DataImport]をクリックします。
ここで、forumを選んでExecuteすると、solrconfig.xmlで設定したData Import Handlerを実行して、PostgresからデータをSolrにインポートします。
(いくら待っても画面が更新されない場合は、[Reflesh Status]を押してみる)
成功していたら、[Query]で検索してみます。
ちゃんとPostgresに入れた3つのデータが検索されました!
参考資料
-
2015/12/30追記 collection1はデフォルトでは存在しなかったかも。なければ、Solrのコンソールなどで作成してください。 ↩