ElasticSearchで日本語の文章を検索できるようにする

## やること
dockerでコンテナを立て、ElasticSearchに日本語を含むデータを投入し日本語で検索できるようにします。

### Dockerコンテナを立てる
[Elasticsearch公式](https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html)に沿って進めます。

docker imageをDocker Hubからインストールします。

```
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.10.1
```

docker-compose.ymlを書きます。
公式では3つのクラスターを立てていますが、今回は一つのクラスタのみにします。

```docker-compose.yml
version: '2.2'
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.10.1
    container_name: es01
    environment:
      - node.name=es01
      - cluster.name=es-docker-cluster
      - cluster.initial_master_nodes=es01
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elastic
  
volumes:
  data01:
    driver: local

networks:
  elastic:
    driver: bridge
```

docker-compose.ymlがあるディレクトリで以下を実行し、コンテナを起動します。


```
docker-compose up
```

### 日本語解析プラグインをインストールする

[公式の日本語解析プラグイン（kuromoji）](https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-kuromoji.html#analysis-kuromoji)をインストールします。
コンテナにログインします。

```
docker exec -it 立ち上げたコンテナID /bin/bash 
```

（↓docker上）

```
sudo bin/elasticsearch-plugin install analysis-kuromoji
```

インストール後、dockerコンテナからは出て、dockerを再起動します。

```
docker restart 立ち上げたコンテナID
```

ローカルに戻って、以下を実行します。

```
curl http://localhost:9200/_nodes/plugins?pretty
```

analysis-kuromoji があればOKです。


```
（略）
 "plugins" : [
        {
          "name" : "analysis-kuromoji",
          "version" : "7.6.2",
          "elasticsearch_version" : "7.6.2",
          "java_version" : "1.8",
          "description" : "The Japanese (kuromoji) Analysis plugin integrates Lucene kuromoji analysis module into elasticsearch.",
          "classname" : "org.elasticsearch.plugin.analysis.kuromoji.AnalysisKuromojiPlugin",
          "extended_plugins" : [ ],
          "has_native_controller" : false
        }
（略）
```

### indexを作成する
今回Elasticsearch7で動かしているのでtypeはありません。
美術館・博物館を検索できるようなindexとします。

```
curl -X PUT http://localhost:9200/museum?pretty
```
↑の実行後以下で作成したindex名が表示されればOKです。

```
curl -X GET http://localhost:9200/_cat/indices?v
```

### indexにデータを投入する

サンプルとして、以下のデータを投入します。
jsonファイルを作成します。


``` sample.json
{"pref_id": "13", "city_id": "13101", "name": "国立美術館東京国立近代美術館","location": [139.7547383, 35.6905368]}
{"pref_id": "13", "city_id": "13106", "name": "上野の森美術館", "location": [139.7747384, 35.7127347]}
```

museumは作成したindex名、作成したデータはsample.jsonとなります。

```
curl -H "Content-Type: application/json" -XPOST http://localhost:9200/museum/_bulk --data-binary @sample.json
```

以下で登録したデータが取得できればOKです。

```
curl -XGET http://localhost:9200/facility/_search?pretty
```

### クエリの作成
Elasticsearchの文書の検索機能には何種類かあります（部分一致,完全一致など）が、ありますが
今回は```match_phrase```を使います。
```match_phrase```は指定した句を含むデータを返すことができます。

```sample_query.json
{
  "query": {"match_phrase": { "name": "国立" } } 
}
```

### 検索
作成したjsonを指定して検索します。

```
curl -H "Content-Type: application/json" -X GET http://localhost:9200/facility/_search --data-binary @sample_query.json
```

結果として条件に当てはまるデータが取得できるようになりました。
（一部省略しています。）

```

{
  "took":324,
  "timed_out":false,
  "_shards":
    {
      "total":1,
      "successful":1,
      "skipped":0,
      "failed":0
    },
  "hits":
    {
      "_index":"museum",
      "_type":"_doc",
      "_id":"1",
      "_source":
        {
          "pref_id": "13", 
          "city_id": "13103", 
          "name": "国立美術館国立新美術館",  
          "location": [139.7263974, 35.6652779]
        }
     }
}
```


## 参考
https://www.elastic.co/guide/jp/elasticsearch/reference/current/gs-executing-searches.html
https://blog.chocolapod.net/momokan/entry/114