目次
Solr 4.4に取り込まれる予定のチケットで、気になるものを見つけたのでいつものごとく調べてみました。
元となるチケットはこちら。SOLR-4897。
スキーマレス?
Solrはschema.xmlにデータの定義(フィールドタイプやフィールドなど)を記述して、データを登録する全文検索システムです。 これまでのSolrではこの設定ファイルを元にデータを登録するフィールド名を決定しており、 変更を行う場合はSolrのコアを再起動するなどの手順が必要でした。(※ダイナミックフィールドはすこし特殊)
それだと、Solrを管理するのがめんどくさいですね?という感じで現れたのがSchemaREST APIです。(たぶん。)
Schema REST API
Solr 4.2から導入されたSolrのスキーマに関する情報を提供するためのREST APIです。 4.2で導入されたのはあくまでもschema.xmlの情報を取得するためのAPIでした。 たとえば、Fieldの一覧を取得するとか。
4.4から、フィールドの追加(変更、削除はできない)ができるようになりました。あくまでも、フィールドの追加で、フィールドタイプなどの追加はまだできません。(できるようになるのかもわからないですが。) フィールドの追加方法などはWikiに記載がありました。
ということで、簡単に試してみることに。
起動方法
exampleディレクトリの下にexample-schemalessというディレクトリが新設されています。 ここに、スキーマレスモード用の設定がされているファイルが入っているので、こちらを利用します。
cd $SOLR/example
java -Dsolr.solr.home=example-schemaless/solr -jar start.jar
ログにいくつかWARNが出ますが、影響の内パス設定ミスなので無視してOKです。
最初に定義されているフィールドは「id」と「_version_」のみになります。(Schema Browserなどで確認できます。あ、REST APIでもいいですね。http://localhost:8983/solr/schema/fields)
スキーマの更新
さて、フィールドを追加してみます。 PUTを利用すると1フィールドの追加が可能です。 「fugatext」というフィールド名でフィールドを追加しています。今のところJSONのみ対応みたいです。
$ curl -X PUT http://localhost:8983/solr/schema/fields/fugatext -H 'Content-Type: application/json' -d '{"type":"text_ja","stored":false,"multiValued":true}'
{
"responseHeader":{
"status":0,
"QTime":18}}
追加できたかどうかもREST APIで取得してみます。
$ curl http://localhost:8983/solr/schema/fields
{
"responseHeader":{
"status":0,
"QTime":0},
"fields":[{
"name":"_version_",
"type":"long",
"indexed":true,
"stored":true},
{
"name":"fugatext",
"type":"text_ja",
"multiValued":true,
"stored":false},
{
"name":"id",
"type":"string",
"multiValued":false,
"indexed":true,
"required":true,
"stored":true,
"uniqueKey":true}]}
追加できました。 ちなみに、同じフィールド名を追加しようとするとエラーが帰ってきます。
$ curl -X PUT http://localhost:8983/solr/schema/fields/fugatext -H 'Content-Type: application/json' -d '{"type":"text_ja","stored":false,"multiValued":true}'
{
"responseHeader":{
"status":400,
"QTime":1},
"error":{
"msg":"Field 'fugatext' already exists.",
"code":400}}
設定の違い
example-schemalessのsolrconfig.xmlは以下の設定が通常のexampleとは異なるようです。
schemaFactoryの設定
schemaをAPIから変更可能にする設定です。これまでの変更しない設定の場合はClassicIndexSchemaFactory
を指定します。
...
<schemaFactory class="ManagedIndexSchemaFactory">
<bool name="mutable">true</bool>
<str name="managedSchemaResourceName">managed-schema</str>
</schemaFactory>
...
update.chainの設定
更新処理(update関連のリクエストハンドラ「/update」とか)には次のような設定が追加されていました。(1006行目あたり)
<requestHandler name="/update" class="solr.UpdateRequestHandler">
<!-- See below for information on defining
updateRequestProcessorChains that can be used by name
on each Update Request
-->
<lst name="defaults">
<str name="update.chain">add-unknown-fields-to-the-schema</str>
</lst>
</requestHandler>
「add-unknown-fields-to-the-schema」というupdate.chainが指定されています。このchainの定義自体は1669行目くらいに存在します。 (長い。。。)
<!-- Add unknown fields to the schema
An example field type guessing update processor that will
attempt to parse string-typed field values as Booleans, Longs,
Doubles, or Dates, and then add schema fields with the guessed
field types.
This requires that the schema is both managed and mutable, by
declaring schemaFactory as ManagedIndexSchemaFactory, with
mutable specified as true.
See http://wiki.apache.org/solr/GuessingFieldTypes
-->
<updateRequestProcessorChain name="add-unknown-fields-to-the-schema">
<processor class="solr.RemoveBlankFieldUpdateProcessorFactory"/>
<processor class="solr.ParseBooleanFieldUpdateProcessorFactory"/>
<processor class="solr.ParseLongFieldUpdateProcessorFactory"/>
<processor class="solr.ParseDoubleFieldUpdateProcessorFactory"/>
<processor class="solr.ParseDateFieldUpdateProcessorFactory">
<arr name="format">
<str>yyyy-MM-dd'T'HH:mm:ss.SSSZ</str>
<str>yyyy-MM-dd'T'HH:mm:ss,SSSZ</str>
<str>yyyy-MM-dd'T'HH:mm:ss.SSS</str>
<str>yyyy-MM-dd'T'HH:mm:ss,SSS</str>
<str>yyyy-MM-dd'T'HH:mm:ssZ</str>
<str>yyyy-MM-dd'T'HH:mm:ss</str>
<str>yyyy-MM-dd'T'HH:mmZ</str>
<str>yyyy-MM-dd'T'HH:mm</str>
<str>yyyy-MM-dd HH:mm:ss.SSSZ</str>
<str>yyyy-MM-dd HH:mm:ss,SSSZ</str>
<str>yyyy-MM-dd HH:mm:ss.SSS</str>
<str>yyyy-MM-dd HH:mm:ss,SSS</str>
<str>yyyy-MM-dd HH:mm:ssZ</str>
<str>yyyy-MM-dd HH:mm:ss</str>
<str>yyyy-MM-dd HH:mmZ</str>
<str>yyyy-MM-dd HH:mm</str>
<str>yyyy-MM-dd</str>
</arr>
</processor>
<processor class="solr.AddSchemaFieldsUpdateProcessorFactory">
<str name="defaultFieldType">text_general</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>
<processor class="solr.LogUpdateProcessorFactory"/>
<processor class="solr.RunUpdateProcessorFactory"/>
</updateRequestProcessorChain>
使ってるUpdateProcessorはこんな感じみたいです。最後の2つはこれ用じゃないので省略。
プロセッサ名 | 説明 |
---|---|
RemoveBlankFieldUpdateProcessorFactory | 値がないフィールドは除去 |
ParseBooleanFieldUpdateProcessorFactory | スキーマに定義されていないフィールドで、値がBooleanとしてパースできたら、Boolean型とする。 |
ParseLongFieldUpdateProcessorFactory | スキーマに定義されていないフィールドで、値がLongとしてパースできたら、Long型とする。 |
ParseDoubleFieldUpdateProcessorFactory | スキーマに定義されていないフィールドで、値がDoubleとしてパースできたら、Double型とする。 |
ParseDateFieldUpdateProcessorFactory | スキーマに定義されていないフィールドで、値がDateとしてパースできたら、Date型とする。(パースの形式がformatで列挙されてる) |
AddSchemaFieldsUpdateProcessorFactory | 入力されたドキュメントの中でスキーマに定義されていないフィールド(静的、動的両方)を見つけた時に、フィールドの値の型を元にフィールド型をマッピングする。 |
とここまで見てきたところで、スキーマレスという名前の意図がちょっとわかったかも。
定義されてないフィールドを持ったデータを登録
起動時には定義されてないフィールドをもったデータを登録してみます。 boolean型で試してみることに。以下のデータを管理画面のデータ登録画面から登録します。(http://localhost:8983/solr/#/collection1/documents) (タイトルでbooleanってわかりにくいですが)
{"id":"change.me","title":true, "price":1.25, "fuga":"100,200"}
エラーは出ません。で、またフィールド一覧を取得すると。
$ curl http://localhost:8983/solr/schema/fields
{
"responseHeader":{
"status":0,
"QTime":1},
"fields":[{
"name":"_version_",
"type":"long",
"indexed":true,
"stored":true},
{
"name":"fuga",
"type":"tlongs"},
{
"name":"fugatext",
"type":"text_ja",
"multiValued":true,
"stored":false},
{
"name":"id",
"type":"string",
"multiValued":false,
"indexed":true,
"required":true,
"stored":true,
"uniqueKey":true},
{
"name":"price",
"type":"tdoubles"},
{
"name":"title",
"type":"booleans"}]}
おー、最後にtitleが追加されてます。他にもfugaやpriceも。(日付は手を抜きました。。。)
感想
詳細までは追いかけてないですが、こんなかんじです。 フィールド追加が可能になるのはいいんじゃないでしょうか。SolrCloudの機能との関連もあるのかもしれません。ZooKeeperへの出力も実装されてそうなので。
ただ、機械的に出力されたschema.xml(exampleだとmanaged-schemaというファイル)には_「DO NOT EDIT」_との記述があるので、修正するとなにかおきてしまうかもしれないですねぇ。 現時点では、フィールドタイプの変更やフィールドの更新、削除に関してはSolrCoreの再起動などの手順が必要です。 あと、変なデータ(タイプミスとか)が登録されたりしないかってのは気になりますね。
※ちなみに、別の人が気づいたんですが、ちょっとバグが有ったみたいで、代わりにチケットつくったらキリ番(SOLR-5000) ゲットしましたw
comments powered by Disqus
See Also by Hugo
- Riak Meetup Tokyo #2に参加しました。#riakjp
- 新しいsolr.xmlとCore探索ロジック
- Cloudera Searchメモ(妄想版)
- Solr4.3.0のChangesを訳してみた。(Jugemより移植)
- 「Apache Solr入門」のサンプルのKuromojiとlucene-gosen対応(2章~4章)(Jugemより移植)