ElasticSearchで禁止ワードチェックしてみた

Elasticsearchを使っていてpercolator機能で何か面白い使い方できないかなぁということで遊んでみたのでメモを。

０. 環境
ElasticSearch 1.0.1
elasticsearch-analysis-kuromoji 2.0.0

１. 下準備
index,mappingを作成します.
messageのindex_analyzerは調べたいテキストを解析するanalyzeするanalyzer、
search_analyzerはNGワードの検索クエリを解析するanalyzerになる点に注意して下さい。

```
[vagrant@node1 ~]$ curl -XPUT  http://localhost:9200/filter/ -d '
{
    "index":{
        "analysis":{
            "analyzer" : {
                "kuromoji" : {
                    "tokenizer" : "kuromoji_tokenizer"
                }
            }
        }
    }
}
'
{"acknowledged":true}
```
```
[vagrant@node1 ~]$ curl -XPUT localhost:9200/filter/message/_mapping -d '
{
    "message": {
        "_id": {},
        "properties": {
            "message": {
                "type": "string",
                "index_analyzer": "kuromoji",
                "search_analyzer": "whitespace"
            },
            "filter_id": {
                "type": "long",
                "include_in_all": false
            }
        }
    }
}
'
{"acknowledged":true}
```
```
[vagrant@node1 ~]$ curl -XPUT localhost:9200/filter/.percolator/_mapping -d '
{
  ".percolator": {
    "_id": {
        "index": "not_analyzed",
        "path" : "filter_id"
    },
    "properties": {
        "query": {
            "enabled": false,
            "type": "object"
        },
        "filter_id": {
            "type": "long"
        }
    }
  }
}
'
{"acknowledged":true}
```
２. 禁止ワード登録

```
[vagrant@node1 ~]$ curl -XPOST localhost:9200/filter/.percolator/ -d '
{
    "query": {
        "match": {
            "message": "売春 殺す 死ね"
        }
    },
    "filter_id" : 1
}
'
{"_index":"filter","_type":".percolator","_id":"1","_version":1,"created":true}
```

```
[vagrant@node1 ~]$  curl -XPOST localhost:9200/filter/.percolator/ -d '
{
    "query": {
        "match": {
            "message": "ブタ"
        }
    },
    "filter_id" : 2
}
'
{"_index":"filter","_type":".percolator","_id":"2","_version":1,"created":true}
```

３. NGチェック
禁止ワードが含まれているかどうかの判定だけではなく、
highlight指定してやると該当箇所を伏字（ニ○ニ○動画風)にし易い形式でも取得することが可能です。


```:禁止ワードの有無を判定
[vagrant@node1 ~]$ curl -XGET localhost:9200/filter/message/_percolate?pretty -d '
{
    "doc": {
        "message": "nobuta@github死ね"
    }
}
'
{
  "took" : 1,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "total" : 1,
  "matches" : [ {
    "_index" : "filter",
    "_id" : "1"
  } ]
}
```
```:禁止ワード部分の抽出
[vagrant@node1 ~]$ curl -XGET localhost:9200/filter/message/_percolate?pretty -d '
{
    "highlight": {
        "fields": {
            "message": {
                "pre_tags": [ "(" ],
                "post_tags": [ ")" ]
            }
        }
    },
    "size": 10,
    "doc": {
        "message": "nobuta@github死ね"
    }
}
'
{
  "took" : 30,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "total" : 1,
  "matches" : [ {
    "_index" : "filter",
    "_id" : "1",
    "highlight" : {
      "message" : [ "nobuta@github(死ね)" ]
    }
  } ]

```
```:禁止ワード部分の抽出(複数のパターン)
[vagrant@node1 ~]$ curl -XGET localhost:9200/filter/message/_percolate?pretty -d '
{
    "highlight": {
        "fields": {
            "message": {
                "pre_tags": [ "(" ],
                "post_tags": [ ")" ]
            }
        }
    },
    "size": 10,
    "doc": {
        "message": "ノブタ@github殺す"
    }
}
'
{
  "took" : 3,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "total" : 2,
  "matches" : [ {
    "_index" : "filter",
    "_id" : "1",
    "highlight" : {
      "message" : [ "ノブタ@github(殺す)" ]
    }
  }, {
    "_index" : "filter",
    "_id" : "2",
    "highlight" : {
      "message" : [ "ノ(ブタ)@github殺す" ]
    }
  } ]
}
```

４. 最後に
ElasticSearchといえば全文検索であったりKibanaが主流ですが、こんな使い方もできるんじゃないだろうかってことで紹介をしてみました。
他にもこんな使い方してるよって方いましたら是非教えてください。