solrにschema設定してデータをpostする

# Solrを導入とコア作成までは以下で実施する
* https://qiita.com/junk1400/items/b191750f72caf7138e83
* コアの名前はtestとする

# schemaを考える（簡易版）

* 簡易スキーマーを下記とする


| name | type | stored | indexed | multivalued |
|--------|--------|--------|--------|--------|
| item_id | string | true | true | false |
| isbn | string | true | true | false |
| item_nm | text_ja | true | true | false |
| item_yomi | text_ja | true | true | false |
| item_cls | pint | true | true | false |
| cont_intr | text_ja | true | true | false |
| price | ping | true | true | false |
| sls_st_dttm | pdate | true | true | false |
| sls_ed_dttm | pdate | true | true | false |

# schema add field
* 以下のPOSTでスキーマーを設定する

```shell

curl -X POST -H 'Content-type:application/json' --data-binary '{
    "add-field": [
        {
            "name": "item_id",
            "type": "string",
            "stored": true,
            "indexed": true,
            "multiValued": false,
        },
        {
            "name": "isbn",
            "type": "string",
            "stored": true,
            "indexed": true,
            "multiValued": false,
        },
        {
            "name": "item_nm",
            "type": "text_ja",
            "stored": true,
            "indexed": true,
            "multiValued": false,
        },
        {
            "name": "item_yomi",
            "type": "text_ja",
            "stored": true,
            "indexed": true,
            "multiValued": false,
        },
        {
            "name": "item_cls",
            "type": "pint",
            "stored": true,
            "indexed": true,
            "multiValued": false,
        },
        {
            "name": "cont_intr",
            "type": "text_ja",
            "stored": true,
            "indexed": true,
            "multiValued": false,
        },
        {
            "name": "price",
            "type": "pint",
            "stored": true,
            "indexed": true,
            "multiValued": false,
        },
        {
            "name": "sls_st_dttm",
            "type": "pdate",
            "stored": true,
            "indexed": true,
            "multiValued": false,
        },
        {
            "name": "sls_ed_dttm",
            "type": "pdate",
            "stored": true,
            "indexed": true,
            "multiValued": false,
        }
    ]
}' 'http://localhost:8983/solr/test/schema'
```

* postでschemaを設定する場合、coreのリロードが必要なく即時反映される

* 管理画面でschemaが設定されたことを確認する
http://127.0.0.1:8983/solr/#/test/schema

## jsonでデータを投入する

投入するjson

```prd_data.json
[
  {
    "item_id" : "001",
    "isbn" : "9784041062050",
    "item_nm" : "異世界迷宮でハーレムを(1)",
    "item_yomi" : "いせかいめいきゅうではーれむを",
    "item_cls" : 1,
    "cont_intr" : "怪しげなウェブサイトでゲームキャラメイクをしたら何故か異世界で目覚めた道夫。しかしその世界の「奴隷」制度を知った道夫はゲーム設定時
に獲得したスキルを使い夢のハーレム生活を送るため冒険に出るのだった！",
    "price" : 626,
    "sls_st_dttm" : "2018-01-01"
  }
,
  {
    "item_id" : "002",
    "isbn" : "9784041067215",
    "item_nm" : "異世界迷宮でハーレムを(2)",
    "item_yomi" : "いせかいめいきゅうではーれむを",
    "item_cls" : 1,
    "cont_intr" : "迷宮探索・盗賊退治と命懸けで金策した道夫は、ついに「ロクサーヌ」購入資金を手に入れる。再び商館を訪れた道夫は無事「ロクサーヌ」の所
有者となり、初夜を迎えるべく自分の宿に向かうのだった！？",
    "price" : 626,
    "sls_st_dttm" : "2018-01-01"
  }
]
```
* 以下のコマンドで投入する

```
$ curl 'http://localhost:8983/solr/test/update?commit=true&indent=true' --data-binary @prd_data.json -H 'Content-Type: text/json'
```
## 管理画面で投入したデータを確認する
http://127.0.0.1:8983/solr/#/test/query

## 投入したデータを検索してみる
http://127.0.0.1:8983/solr/test/select?q=item_nm:%E7%95%B0%E4%B8%96%E7%95%8C

## もう一度同じjsonを投入してみる

```
$ curl 'http://localhost:8983/solr/test/update?commit=true&indent=true' --data-binary @prd_data.json -H 'Content-Type: text/json'
```

## 管理画面で投入したデータを確認する
http://127.0.0.1:8983/solr/#/test/query

* データが4件に増えていることが確認できる
* 理由はuniquekeyがidになっていてitem_idがuniquekeyではないため

# uniquekeyを設定する

### インデックスのデータをすべて削除

* 一旦インデックスのデータを削除します

```
$ curl -H 'Content-Type: application/json' 'http://localhost:8983/solr/test/update?commit=true' -d '{ delete: { query: "*:*" }}'
```

### uniquekeyを設定

* managed-schemaファイルにあるuniquekeyを変更します

```shell
vim /data/test/conf/managed-schema

<uniqueKey>id</uniqueKey>
            ↓
<uniqueKey>item_id</uniqueKey>

```

* idフィールドは使用しないので削除します

```
curl -X POST -H 'Content-type:application/json' --data-binary '{
  "delete-field" : { "name":"id" }
}' http://localhost:8983/solr/test/schema
```



### コンテナ再起動
* uniquekeyの設定をmanaged-schemaファイルを開いて行ったため、コンテナの再起動をする

```shell
$ sudo docker restart solr_solr_1
```

* uniquekey確認

```shell
$ curl http://localhost:8983/solr/test/schema/uniquekey?wt=json
```

## jsonを投入してみる

```shell

$ curl 'http://localhost:8983/solr/test/update?commit=true&indent=true' --data-binary @prd_data.json -H 'Content-Type: text/json'
```

## 同じjsonを再度投入してみる

```shell

$ curl 'http://localhost:8983/solr/test/update?commit=true&indent=true' --data-binary @prd_data.json -H 'Content-Type: text/json'
```

* _version_だけが上がっていることが確認できる


# デフォルトサーチフィールド

The Default Search Field

* defaultsearchfieldについて、昔のバージョンではschema.xmlに defaultsearchfield を指定することで、項目指定をしなかった場合にデフォルト項目への検索を実行してくれていたが、Solr7はschemaにdefaultsearchfieldがあるとexceptionを出すようになった。(らしい)
* 代わりにリクエストパラメータで、dfでフィールドを指定する事

## デフォルトサーチ用フィールド作成
デフォルト検索で、商品名、商品名かな、商品説明を検索するようにするには、

* それ用のフィールドを用意（item_defという名前のフィールドを追加します）し、値をコピーフィールドでコピーします
* コピーフィールドでフィルド値をデフォルトサーチフィールド用にコピーすることで登録用のスキーマーを変更せず対応できる

```
curl -X POST -H 'Content-type:application/json' --data-binary '{
    "add-field": [
        {
            "name": "item_def",
            "type": "text_ja",
            "stored": true,
            "indexed": true,
            "multiValued": true,
            "required" : true,
        }
    ]
}' 'http://localhost:8983/solr/test/schema'
```

* デフォルトサーチフィールドで検索したい項目をコピーフィールドで設定する
* 商品名、ヨミ、商品説明を１つのフィールドにコピーする

```
curl -X POST -H 'Content-type:application/json' --data-binary '{
    "add-copy-field": [
        {
            "source":"item_nm",
            "dest": "item_def"
        },
        {
            "source":"item_yomi",
            "dest": "item_def"
        },
        {
            "source":"cont_intr",
            "dest": "item_def"
        }
    ]
}' 'http://localhost:8983/solr/test/schema'
```

* デフォルトで検索してみる。
http://127.0.0.1:8983/solr/test/select?df=item_def&q=%E7%95%B0%E4%B8%96%E7%95%8C

* 結果は0件になる
* 理由：新しいフィールドに対してindexの作成をしていないため

### jsonでデータを入れ直す

```shell

$ curl 'http://localhost:8983/solr/test/update?commit=true&indent=true' --data-binary @prd_data.json -H 'Content-Type: text/json'
```

### デフォルトで検索可能になる
http://127.0.0.1:8983/solr/test/select?df=prd_def&q=%E7%95%B0%E4%B8%96%E7%95%8C


# 「ロクサーヌ」では引っかかるが「ロク」では引っかからない件

*「ロクサーヌ」で検索をすると1件hitするが「ロク」で検索すると1件もhitしない
http://127.0.0.1:8983/solr/test/select?df=item_def&q=%E3%83%AD%E3%82%AF%E3%82%B5%E3%83%BC%E3%83%8C

http://127.0.0.1:8983/solr/test/select?df=item_def&q=%E3%83%AD%E3%82%AF

* 原因は、商品説明にtext_jaを使っており、text_jaが形態素のため名詞「ロクサーヌ」と名詞「ロク」は別物としてhitしない。
* この商品説明の「ロクサーヌ」を「ロク」でhitさせようとする場合、いくつか方法があるが今回はngramを併用する方法を取る

## schemaにngram用のフィールドタイプを追加する
* ngram追加(バイグラム)

```
curl -X POST -H 'Content-type:application/json' --data-binary '{
  "add-field-type" : {
     "name":"text_2gram",
     "class":"solr.TextField",
     "positionIncrementGap":"100",
     "autoGeneratePhraseQueries":"true",
     "analyzer" : {
        "tokenizer":{
           "class":"solr.NGramTokenizerFactory",
           "minGramSize":"2",
           "maxGramSize":"2"}}}
}' 'http://localhost:8983/solr/test/schema'
```
### ngramのフィールドを追加し、コピーフィールドを設定する

```shell
curl -X POST -H 'Content-type:application/json' --data-binary '{
    "add-field": [
        {
            "name": "item_def_ngram",
            "type": "text_2gram",
            "stored": true,
            "indexed": true,
            "multiValued": true,
            "required" : true,
        }
    ]
}' 'http://localhost:8983/solr/test/schema'

curl -X POST -H 'Content-type:application/json' --data-binary '{
    "add-copy-field": [
        {
            "source":"item_nm",
            "dest": "item_def_ngram"
        },
        {
            "source":"item_yomi",
            "dest": "item_def_ngram"
        },
        {
            "source":"cont_intr",
            "dest": "item_def_ngram"
        }
    ]
}' 'http://localhost:8983/solr/test/schema'
```


## jsonでデータを入れ直す
* schemaに新しい項目を追加したらindexを作り直す

```shell
$ curl 'http://localhost:8983/solr/test/update?commit=true&indent=true' --data-binary @prd_data.json -H 'Content-Type: text/json'
```

## ngramで検索する
http://127.0.0.1:8983/solr/test/select?df=item_def_ngram&q=%E3%83%AD%E3%82%AF%E3%82%B5%E3%83%BC%E3%83%8C

http://127.0.0.1:8983/solr/test/select?df=item_def_ngram&q=%E3%83%AD%E3%82%AF

* どちらも検索できる。
* 形態素とngramはどちらが良いではなく、組み合わせて使うのが良い
* 形態素、ngramともに特性を理解して使用しないと検索結果や検索順位に多大な影響を及ぼす
* 前はhitしたのにちょっと変更しただけで、hitしなくなった等等



## memo
### インデックスのデータをすべて削除

```
$ curl -H 'Content-Type: application/json' 'http://localhost:8983/solr/test/update?commit=true' -d '{ delete: { query: "*:*" }}'
```