Solr 6.1.0 にコアを追加していく


# まとめ
- `managedSchema` でコアを作って REST API でコアを編集したりできるけど、個人的には `ClassicIndexSchemaFactory` が好きです。
- 結局 `solr.solr.home` にファイルを追加しないとコアが作れないので完全に RESTful な制御はできていない気がする

# 前置き
[Solr 6.0.1 インストールしてからコアの追加まで](http://qiita.com/debari/items/305c4a945572754e0b97) や [Solr 6.1.0 をインストールスクリプト使わずに使う](http://qiita.com/debari/items/971b96b9fadd3131ca7d) の最後に「次回はコアをちゃんと作ります」とか言っていたのに全然作っていなかった問題を解決しておこうと思います。よーし、コア作るぜー。

# とりあえず作る
とりあえず動かします。余談ですがフォアグラウンドで動かすと Java で発生している Exception が丸見えになるので開発中は便利です。実運用する時はフォアグラウンドで動かす意味はありませんが開発中はフォアグラウンドで全然問題ないと思います。ということなのでインストールスクリプトは使わず普通にコマンドラインから起動します。

```sh
$ cd solr-6.1.0/server
$ java -jar start.jar --module=http
```

はい。起動しました。では早速APIを叩いてコアを作ろうと思います。

```sh
$ curl 'http://localhost:8983/solr/admin/cores?wt=json&action=CREATE&name=core1'
```

```json
{
  "responseHeader": {
    "status": 400,
    "QTime": 17
  },
  "error": {
    "metadata": [
      "error-class",
      "org.apache.solr.common.SolrException",
      "root-error-class",
      "org.apache.solr.core.SolrResourceNotFoundException"
    ],
    "msg": "Error CREATEing SolrCore 'core1': Unable to create core [core1] Caused by: Can't find resource 'solrconfig.xml' in classpath or '/home/vagrant/solr-6.1.0/server/solr/core1'",
    "code": 400
  }
}
```
ダメでした。 solr は solr.solr.home というパラメータを持ち、このパラメータで指定したディレクトリにコア作成に必要なファイルが存在しなければなりません。何も指定しなければ start.jar と同じディレクトリにある `solr/` ディレクトリ以下が solr.solr.home になります。まだまだ完全に REST API だけでコア作ったりはできない模様です。
今回は `/home/vagrant/solr-6.1.0/server` に start.jar があるので `/home/vagrant/solr-6.1.0/server/solr/corename` に設定ファイルが必要になります。もうちょっと正確に言うと、`/home/vagrant/solr-6.1.0/server/solr/corename/conf` に設定ファイルが必要です。`/home/vagrant/solr-6.1.0/server/solr/corename/data` にはデータが入っていきます。
何故か `server/solr/configsets` 以下に設定ファイルのサンプルがあるのでコレを使ってみましょう。

```sh
$ cp -r configsets/basic_configs core1
$ curl 'http://localhost:8983/solr/admin/cores?wt=json&action=CREATE&name=core1'
```

```json
{
  "responseHeader": {
    "status": 0,
    "QTime": 508
  },
  "core": "core1"
}
```
できた。終わり。あとは core1/conf に入っている設定ファイルの中身をカスタマイズしたりするといいと思います。

# コアをカスタマイズする
そのまま使ったところで自分が持ってるデータに使えるわけでもないのでカスタマイズが必要です。

## スキーマは schema.xml で管理するように設定
とりあえず `solrconfig.xml` を開いて、`<luceneMatchVersion>` の下の行あたりに `<schemaFactory class="ClassicIndexSchemaFactory"/>` を追記します。

```solrconfig.xml
  <luceneMatchVersion>6.1.0</luceneMatchVersion>
+ <schemaFactory class="ClassicIndexSchemaFactory"/>
```

Solr 6.1.0 ではデフォルトでスキーマレスモードを使うようになっているのですが、追加するこの1行にはスキーマレスモードを使わないという熱い気持ちが込められています。別に使ってもいいんですが、結局ファイル管理だし。

`ClassicIndexSchemaFactory` では `schema.xml` が必要になるのですが、これは `managed-schema` と中身が一緒なので、まるっと移動しておきます。

```
$ mv managed-schema schema.xml
```

あとは schema.xml をいじくり倒せばだいたいコアができあがります。

## フィールドタイプを追加する

とりあえず 1gram 検索でも作る事にします。

```
<fieldType name="text_1gram" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="false">
    <analyzer type="index">
        <charFilter class="solr.HTMLStripCharFilterFactory"/>
        <tokenizer class="solr.NGramTokenizerFactory" minGramSize="1" maxGramSize="1"/>
        <filter class="solr.CJKWidthFilterFactory"/>
        <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true" tokenizerFactory="solr.NGramTokenizerFactory" minGramSize="1" maxGramSize="1"/>
        <filter class="solr.LowerCaseFilterFactory"/>
    </analyzer>
    <analyzer type="query">
        <tokenizer class="solr.NGramTokenizerFactory" minGramSize="1" maxGramSize="1"/>
        <filter class="solr.CJKWidthFilterFactory"/>
        <filter class="solr.LowerCaseFilterFactory"/>
    </analyzer>
</fieldType>
```

できた。せっかくなのでフィールドも用意します。

```
<field name="body" type="string" indexed="false" stored="true" />
<copyField name="body__text_1gram" type="text_1gram" indexed="true" stored="false" />
```

これらは schema.xml の適切な場所に空気を読んで貼り付けます。schema.xml の変更内容はコアをリロードしないと反映されないので、リロードします。

```
$ curl 'http://localhost:8983/solr/admin/cores?wt=json&action=RELOAD&core=core1'
```

いちいち RELOAD しないために ManagedSchema があると便利なのかな。まぁ、さておき、コレで何か body とかのデータを投入すると 1-gram での全文検索ができるようになるわけですね。