前回はDockerにElasticsearchの環境をつくるところまで進めました
第3回目はElasticsearchにテストデータを用意するところまでです
やりたいことのおさらい
キーワードを入力していくとキーワード候補エリア、関連エリア(もしかして、、、これ?みたいな)が表示されるやつを作ります
テストデータを用意
サジェストできそうなデータを用意していきます
クジラ飛行机さんがパブリックドメインで公開してくれている英和辞書データを使います。
ありがとうございます。
https://github.com/kujirahand/EJDict
1.templateを作成
こちらは以下の記事を参考にして作成していきます
Elasticsearch 日本語の為のスキーマレス環境構築
{
"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を登録
特にスクリプトを用意する必要はないのですが、
コマンド実行を覚えられないのでスクリプトを作ります
# !/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
3.importプログラムを作成
ejdictインデックスにword、meaningフィールドを作成します
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"
}
},
次回はいよいよサジェストフォームを作っていく予定です