Elasticsearchでメールアドレスを登録する際、ドメイン名でのみヒットするようにしたいということがあったので、そのいった処理ができるようanalyzerを設定してみたのでその備忘。 今まで知らなかったのだけど、Analyzerで指定できるchar_filterでは正規表現での値の置換が行えるらしく、それで@より前を全て削除することでドメインのみをtokenとして登録できるようだ。

以下、定義用のjsonサンプル。

{
  "settings": {
    "analysis": {
      "analyzer": {
        "domain_split_analyzer": {
          "type": "custom",
          "char_filter": [
            "domain_split_filter"
          ],
          "tokenizer": "domain_tokenizer"
        }
      },
      "char_filter": {
        "domain_split_filter": {
          "type": "pattern_replace",
          "pattern": ".+@",
          "replacement": ""
        }
      },
      "tokenizer": {
        "domain_tokenizer": {
          "type": "PathHierarchy",
          "delimiter": ".",
          "reverse": true
        }
      }
    }
  }
}

これを実際にElasticsearchで定義してanalyzerにメールアドレスをPOSTした結果が以下。

test@TEST-elasticsearch:~$ cat es_mapping.json
{
  "settings": {
    "analysis": {
      "analyzer": {
        "domain_split_analyzer": {
          "type": "custom",
          "char_filter": [
            "domain_split_filter"
          ],
          "tokenizer": "domain_tokenizer"
        }
      },
      "char_filter": {
        "domain_split_filter": {
          "type": "pattern_replace",
          "pattern": ".+@",
          "replacement": ""
        }
      },
      "tokenizer": {
        "domain_tokenizer": {
          "type": "PathHierarchy",
          "delimiter": ".",
          "reverse": true
        }
      }
    }
  }
}
test@TEST-elasticsearch:~$ curl -XPUT 'localhost:9200/test' -d  @es_mapping.json
{"acknowledged":true,"shards_acknowledged":true}
test@TEST-elasticsearch:~$
test@TEST-elasticsearch:~$ curl 'localhost:9200/test/_analyze?analyzer=domain_split_analyzer&pretty' -d 'aieuo@test.co.jp'
{
  "tokens" : [
    {
      "token" : "test.co.jp",
      "start_offset" : 6,
      "end_offset" : 16,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "co.jp",
      "start_offset" : 11,
      "end_offset" : 16,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "jp",
      "start_offset" : 14,
      "end_offset" : 16,
      "type" : "word",
      "position" : 0
    }
  ]
}
test@TEST-elasticsearch:~$ curl 'localhost:9200/test/_analyze?analyzer=domain_split_analyzer&pretty' -d 'aieuo@xxx.test.co.jp'
{
  "tokens" : [
    {
      "token" : "<span style="color: #ff0000;">xxx.test.co.jp</span>",
      "start_offset" : 6,
      "end_offset" : 20,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "<span style="color: #ff0000;">test.co.jp</span>",
      "start_offset" : 10,
      "end_offset" : 20,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "<span style="color: #ff0000;">co.jp</span>",
      "start_offset" : 15,
      "end_offset" : 20,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "<span style="color: #ff0000;">jp</span>",
      "start_offset" : 18,
      "end_offset" : 20,
      "type" : "word",
      "position" : 0
    }
  ]
}

いい感じにドメインだけをtokenとして登録してくれている。