vuejsでsuggestフォームを作る3



[前回](https://qiita.com/hir00/items/e4ad83e1140a8bf3354c)はDockerにElasticsearchの環境をつくるところまで進めました
第3回目はElasticsearchにテストデータを用意するところまでです

やりたいことのおさらい
---
キーワードを入力していくとキーワード候補エリア、関連エリア（もしかして、、、これ？みたいな）が表示されるやつを作ります

テストデータを用意
---

サジェストできそうなデータを用意していきます

クジラ飛行机さんがパブリックドメインで公開してくれている英和辞書データを使います。
ありがとうございます。
https://github.com/kujirahand/EJDict


#### 1.templateを作成

こちらは以下の記事を参考にして作成していきます
[Elasticsearch 日本語の為のスキーマレス環境構築](https://medium.com/hello-elasticsearch/elasticsearch-a52fd3ac783e)


```bash
{
  "template": "ejdict",
  "settings": {
    "number_of_shards" : 1,
    "number_of_replicas" : 0,
    "analysis": {
      "filter": {
        "romaji": {
          "type": "kuromoji_readingform",
          "use_romaji": false
        }
      },
      "tokenizer": {
        "kuromoji_search_tokenizer": {
          "type": "kuromoji_tokenizer",
          "mode": "search"
        },
        "forward_match_tokenizer": {
          "type": "edge_ngram",
          "min_gram": 1,
          "max_gram": 30,
          "token_chars": [
            "letter",
            "digit"
          ]
        },
        "include_match_tokenizer": {
          "type": "nGram",
          "min_gram": 2,
          "max_gram": 15,
          "token_chars": [
            "letter",
            "digit"
          ]
        }
      },
      "analyzer": {
        "kuromoji_search_analyzer": {
          "type": "custom",
          "char_filter": [
            "html_strip",
            "kuromoji_iteration_mark"
          ],
          "tokenizer": "kuromoji_search_tokenizer",
          "filter": [
            "cjk_width",
            "lowercase",
            "kuromoji_stemmer",
            "kuromoji_part_of_speech",
            "romaji"
          ]
        },
        "include_match_analyzer": {
          "type": "custom",
          "char_filter": ["html_strip"],
          "tokenizer": "include_match_tokenizer",
          "filter": ["cjk_width", "lowercase"]
        },
        "forward_match_analyzer": {
          "type": "custom",
          "char_filter": [
            "html_strip"
          ],
          "tokenizer": "forward_match_tokenizer"
        }
      }
    }
  },
  "mappings": {
    "_doc": {
      "dynamic_templates": [
        {
          "word_field": {
            "match": "word",
            "match_pattern": "regex",
            "match_mapping_type": "string",
            "mapping": {
              "type": "text",
              "fields": {
                "raw": {
                  "type": "keyword"
                },
                "include_match": {
                  "type": "text",
                  "analyzer": "include_match_analyzer"
                },
                "forward_match": {
                  "type": "text",
                  "analyzer": "forward_match_analyzer"
                }
              }
            }
          }
        },
        {
          "meaning_field": {
            "match": "meaning",
            "match_pattern": "regex",
            "match_mapping_type": "string",
            "mapping": {
              "type": "text",
              "fields": {
                "raw": {
                  "type": "keyword"
                },
                "ja_search": {
                  "type": "text",
                  "analyzer": "kuromoji_search_analyzer"
                },
                "include_match": {
                  "type": "text",
                  "analyzer": "include_match_analyzer"
                },
                "forward_match": {
                  "type": "text",
                  "analyzer": "forward_match_analyzer"
                }
              }
            }
          }
        }
      ]
    }
  }
}
```

前方一致、include検索ができるようにmulti fieldを定義しています
（うまく検索できるかはサジェストフォームを作成しながら検証していきます。一旦これで）

#### 2.templateを登録

特にスクリプトを用意する必要はないのですが、
コマンド実行を覚えられないのでスクリプトを作ります

```bash
#!/bin/bash
set -eu

if [ ! -d EJDict ]; then
  git clone https://github.com/kujirahand/EJDict
fi

echo "init template...."
base_root=$(cd $(dirname $0); pwd)
template_path=${base_root}/ejdict_template.json
curl -H "Content-Type: application/json" -XPUT "http://localhost:9200/_template/ejdic_template?pretty" -d @$template_path
```


#### ３.importプログラムを作成

ejdictインデックスにword、meaningフィールドを作成します

```javascript:import.js
const fs = require('fs');
const request = require('request');
const readline = require("readline-promise").default
const async = require('async');

var importQueue = async.queue(function (opt, callback) {

  const line = opt.line
  const index = opt.index
  const splitLine= line.split("¥t");

  console.log(`add index.....${index}`)

  new Promise((resolve, reject) => {
    try {

      const headers = {
        'Content-Type':'application/json'
      }
      const postData = JSON.stringify({
        "id": index,
        "word": splitLine[0],
        "meaning": splitLine[1]
      });
      const options = {
        url: 'http://localhost:9200/ejdict/_doc/' + index,
        method: 'POST',
        headers: headers,
        body: postData,
      }
      request(options, function (error, response, body) {
        if (error) reject()
        callback(null);
      })
    } catch (e) {
      console.log(e);
      reject();
    }
  });

}, 100);

(async function () {
  try {

    const rlp = readline.createInterface({
      terminal: false,
      input: fs.createReadStream('./EJDict/release/ejdic-hand-utf8.txt')
    });
    rlp.forEach((line, index) => {
      importQueue.push({line:line, index:index});
    });

  } catch (e) {
    console.error(e);
  }
})()
```

実行します

```
% node import.js
```

リクエストしてみます

```
% curl -H "Content-Type: application/json" -XGET "http://localhost:9200/ejdict/_search?pretty"  
```

辞書データが登録されていますね
    
```                      
{
  "took" : 22,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2304,
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "ejdict",
        "_type" : "_doc",
        "_id" : "0",
        "_score" : 1.0,
        "_source" : {
          "id" : 0,
          "word" : "'em",
          "meaning" : "=them"
        }
      },
```

次回はいよいよサジェストフォームを作っていく予定です