mattintosh note

技術書典に出たい人生だった…

Elasticsearch で kuromoji を使って Kibana でタグクラウドを作る

Slack のメッセージを解析するために Elasticsearch に Kuromoji を入れて Kibana でタグクラウドでも作ろうとしたんだけど、まぁいろんなサイト見てもわかりづらいので自分なりにまとめる。

Elasticsearch のバージョンは下記の通り。

Version: 6.5.2, Build: default/tar/9434bed/2018-11-29T23:58:20.891072Z, JVM: 1.8.0_181

Kuromoji のインストール

elasticsearch-plugin コマンドを使って analysis-kuromoji をインストールする。elasticsearch-plugin コマンドは elasticsearch コマンドと同じディレクトリに入っている。

$ ./elasticsearch-plugin install analysis-kuromoji

新しいプラグインを読み込むため Elasticsearch を再起動する。Elasticsearch が起動したらプラグインリストを表示して analysis-kuromoji が有効になっているか確認する。(起動ログにも出力されるのでそちらで確認することもできる)

$ curl localhost:9200/_nodes/plugins?pretty
      :
      "plugins" : [
        {
          "name" : "analysis-kuromoji",
          "version" : "6.5.2",
          "elasticsearch_version" : "6.5.2",
          "java_version" : "1.8",
          "description" : "The Japanese (kuromoji) Analysis plugin integrates Lucene kuromoji analysis module into elasticsearch.",
          "classname" : "org.elasticsearch.plugin.analysis.kuromoji.AnalysisKuromojiPlugin",
          "extended_plugins" : [ ],
          "has_native_controller" : false
        }
      ],
      :

マッピングの設定

スキーマレスでデータを投入しても Kibana では項目として使うことが出来ないので事前にマッピングの設定をしておく必要がある。特に Kuromoji のカスタマイズなどをしない場合の書式は下記のようになる。

{
  "mappings": {
    "<ドキュメントタイプ>": { ❶
    "properties": {
      "<親フィールド名>": { ❷
        "type": "text",
        "analyzer": "kuromoji", ❸
        "fielddata": true, ❹
        "fields": {
          "<子フィールド名>": { ❺
            "type": "keyword",
            "ignore_above": 256
          }
        }
      }
    }
  }
}
  • ❶ … タイプの指定。最近では _doc 一択。
  • ❷ … トップレベルのフィールド名。
  • ❸ … アナライザの指定。ここで kuromoji を指定する。
  • ❹ … ここが true になっていないと Kibana の Aggregation が有効にならず、Terms で表示されない。
  • ❺ … 元のテキストをそのまま保存しておくためのフィールド。使わなければ作らなくてもいい。

インデックス名を my_index、ドキュメントタイプを _doc、トップレベルフィールド名を message とした場合の JSON は下記のようになる。

{
  "mappings": {
    "_doc": {
      "properties": {
        "message": {
          "type": "text",
          "analyzer": "kuromoji",
          "fielddata": true,
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  }
}

データ投入とタグクラウドの作成

せっかくはてなブログを使っているのではてなさんの代表メッセージをお借りして、先程作成したインデックスにデータを投入する。

{
  "message": """
はてなは「知る」「つながる」「表現する」というミッションを掲げ、Webサービスを提供している会社です。

はてなを代表するサービスである「はてなブログ」や「はてなブックマーク」のように、インターネットサービスを通じ、色々な知識を得て、様々な人とコミュニケーションをとり、自分の考えや体験を表現する。そんなサービスをこれからも作っていきます。

自分の持っている技術にこだわりを持ち、研鑽を怠らない人。失敗を恐れずチャレンジ精神をもって新しいことに取り組める人。素敵な表情で働ける人。はてなのサービスやカルチャーに興味を持ち、もっと良くしていける人。インターネットが好きな人。そんな人をはてなは求めています。

世の中をもっと便利におもしろく。一緒に世界を変えていきませんか?
"""
}

Kibana で my_index なインデックスパターンを作成する。messagemessage.keyword ではない)の Aggregatable が有効になっていることを確認する。

f:id:mattintosh4:20190205212911p:plain
Kibana - Management

Discover で投入されたデータを確認してみる。「はてな」で文字列検索が有効になっていることも確認。

f:id:mattintosh4:20190205212457p:plain
Kibana - Discover

Visualize で Tag Cloud を選択して Buckets を message に指定して実行するとタグクラウドが形成される。

f:id:mattintosh4:20190205213324p:plain
Kibana - Visualize (Tag Cloud)

整った文章の場合はあまり変な区切られ方はしないが、Slack のチャットのようにメチャクチャなワードが含まれていると変に分割されることがある。その場合、Buckets の Advanced オプションで Exclude の欄に .(任意の1文字)や ..(任意の2文字)を指定して除外して上げればよい。条件は | で区切ることで複数指定することが出来、ある程度の正規表現を使うことができるようだ。

条件 書式
1文字だけ .
1文字または2文字 .|..
http または https https?
英数字1文字〜4文字 [a-zA-Z0-9]{1,4}

とりあえずうちの Slack では「半角英数字1文字」、「http または https」、「www」、「com」などを [a-zA-Z0-9]|https?|www|com という条件で除外している。

アナライザの設定で事前にフィルタを設定しておけば Slack 内部で変換されたメンション部分や URL を形態素解析の対象から外すこともできるがその話はまた今度。

サンプルスクリプト

今回のテストで使用した下記の JSON を Kibana の Dev Tools に貼り付けていただくとご自分の環境で同じ検証が出来ます。各コマンドは Dev Tools に表示される「▶」ボタンか、実行したい行をクリックして Ctrl + Enter で個別に実行出来るので順番に進めていくと Kuromoji 導入の勉強になるかもしれません。

※インデックス名はご自分の環境に合わせて変更してください。そのまま実行すると DELETE my_indexmy_index が削除されますのでご注意ください。

※データを投入していまうとマッピングの変更ができなくなりますのでインデックスの作成からやり直す必要があります。

f:id:mattintosh4:20190205215317p:plain
Kibana - Dev Tools

DELETE my_index

PUT my_index
{
  "mappings": {
    "_doc": {
      "properties": {
        "message": {
          "type": "text",
          "analyzer": "kuromoji",
          "fielddata": true,
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  }
}

PUT my_index/_doc/1
{
  "message": """
はてなは「知る」「つながる」「表現する」というミッションを掲げ、Webサービスを提供している会社です。

はてなを代表するサービスである「はてなブログ」や「はてなブックマーク」のように、インターネットサービスを通じ、色々な知識を得て、様々な人とコミュニケーションをとり、自分の考えや体験を表現する。そんなサービスをこれからも作っていきます。

自分の持っている技術にこだわりを持ち、研鑽を怠らない人。失敗を恐れずチャレンジ精神をもって新しいことに取り組める人。素敵な表情で働ける人。はてなのサービスやカルチャーに興味を持ち、もっと良くしていける人。インターネットが好きな人。そんな人をはてなは求めています。

世の中をもっと便利におもしろく。一緒に世界を変えていきませんか?
"""
}

GET my_index/_doc/1