elasticsearchのデフォルトのtokenizerは'-'や'&'では分割してくれますが,'_'では分割してくれません.つまり
"elastic-search test_data"
は
elastic, search, test_data
のように分割されます.これをtest, data
のようにunderscoreで分割する方法を探していました.
Word Delimiter Token Filter を使う
filterのword_delimiter
では区切り文字に関する設定を色々変えることができます.詳しくはhttps://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-word-delimiter-tokenfilter.htmlを参照してください.
このword_delimiter
にあるtype_table
を使うと文字の属性(ALPHA, ALPHANUM, DIGIT, SUBWORD_DELIM等)を変えることができます.今回はunderscoreの属性をSUBWORD_DELIMに変えます.
$ curl -XPOST 'http://localhost:9200/test/' -d '
{
"settings": {
"analysis": {
"filter": {
"underscore_splitter": {
"type": "word_delimiter",
"type_table": [
"_ => SUBWORD_DELIM"
]
}
},
"analyzer": {
"default": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"underscore_splitter"
]
}
}
}
}
}
'
でセッテイングを登録し,analyzerの挙動を確認すると,
$ curl 'localhost:9200/test/_analyze' -d 'elastic-search test_data'
{
"tokens": [
{
"token": "elastic",
"start_offset": 0,
"end_offset": 7,
"type": "<ALPHANUM>",
"position": 1
},
{
"token": "search",
"start_offset": 8,
"end_offset": 14,
"type": "<ALPHANUM>",
"position": 2
},
{
"token": "test",
"start_offset": 15,
"end_offset": 19,
"type": "<ALPHANUM>",
"position": 3
},
{
"token": "data",
"start_offset": 20,
"end_offset": 24,
"type": "<ALPHANUM>",
"position": 4
}
]
}
確かにtokenizerがunderscoreで分割しています.
おまけ: オリジナルを残す
また,word_delimiter
は,preserve_original
をtrue
に設定することでindexingする際にオリジナルの文章を残すこともできます.
$ curl -XPOST 'http://localhost:9200/test/' -d '
{
"settings": {
"analysis": {
"filter": {
"underscore_splitter": {
"type": "word_delimiter",
"preserve_original": true,
"type_table": [
"_ => SUBWORD_DELIM"
]
}
},
"analyzer": {
"default": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"underscore_splitter"
]
}
}
}
}
}
'
これにより,"elastic-search test_data"
を,elastic, search, test_data, test, data
のように分割することができます.
更におまけ: Mapping Char Filter を使う
mapping char filter を使うと,indexに登録する際に文字を変換して登録することができます.詳しくはこちら.
これを使って,
{
"settings": {
"analysis": {
"char_filter": {
"my_mapping": {
"type": "mapping",
"mappings": ["_=>-"]
}
},
"analyzer": {
"default": {
"tokenizer": "standard",
"char_filter": [
"my_mapping"
]
}
}
}
}
}
のように無理やり'_'を'-'に変換して登録し,無理やりtest, data
と分割する方法も考えましたが,あまりに汚いので他の方法を探し,上記のやり方にたどり着きました.ただMapping Char Filter自体は色々便利そうです.