インデックスされているコンテンツデータから単語を抽出したい。

当方で運用している日報システムの検索性を高めるために日報データ(RDBストア)を、elasticsearchに流し込みインデックスを作成いたしました。
(初めて全文検索エンジンを利用しまして、elasticsearchを使い始めて2週間程度です。)

ここで非常に初心者的質問で申し訳ないのですが。
この日報データを検索する際のキーワードサジェスト機能(「前方一致」)を作成したいと思っています。

Suggestインデックスを作成し、プロパティーとしてkeyword(type:completion)をもつmappingを作成し、そこに単語データを流し込んでSuggest機能を実装しようと考えております。

"keyword": {
          "type": "completion",
          "analyzer": "kuromojiのアナライザー"
        }

そこで、elasticsearchに流し込んだ日報データ(kuromojiでアナライズ適用)から「単語群」を抽出して、単語データリストを作成しSuggestインデックスに流し込みたいと思っているのですが、どのように単語群を抽出できますでしょうか?
もしくはそれはそもそも可能なのでしょうか?

もしくは、そもそもこういうSuggest機能の作り方は想定されておらず、あくまでも単語データリストはelasticsearch外で自作してからSuggestインデックスに流し込むのが一般的なのでしょうか。

全文検索システムの設計イメージがまだちゃんと持てていないため、もしかしたら設計的におかしな事を言っているのかも知れませんが、せっかく形態素解析や正規化を通じて日報コンテンツの単語リストがelasticsearch内にストアされているのであれば、抽出して利用したいと思って質問させていただきました。

よろしくお願いします。

私もElasticsearchを触って1ヶ月程度の初心者です。
同様にSuggest機能を検討しまして、ここで相談したときのスレッドがございますので、そちらを共有します。

Suggestに関してましては、私もSuggest用のIndexを作成して、そのIndex対して前方一致なりの実装が必要と理解しました。Suggest用のIndexを作成するのが面倒だったので、私の場合は、significanttext-aggregation を使う方法を採りました。

サンプルクエリですが、入力文字列がマッチするドキュメントに対して、significanttexのaggregationをかけています。実行結果として入力文字列と関連が強い名詞の一覧を取得できますので、それをSuggestとして使用しています。

GET {index}/{type}/_search
{
    "size": 0,
    "query": {
        "bool" : {
            "should" : [
                { "match" : {"fielditem.kuromoji": "入力文字" }}
            ]
        }
    },
    "aggs": {
        "my_keywords": {
            "significant_text": {
                "field": "fielditem.meishi",
                "filter_duplicate_text": true
            }
        }
    }
}

この方法で得られたSuggestはまだこちらでも検証段階なので、精度等については調整が必要かと思います。

1 Like

早々のお返事ありがとうございます。

やはり、Suggest機能は別途Indexを作成し、キーワードリスト(なんらかの方法で作成し)を流し込む方法が一般的なんでしょうかね。
(私も現段階ではそれしか思い浮かばなかったので)

個人的には、コンテンツがアナライズ(キーワードに分解されて)されてelasticsearch内で保存されているのであれば、それを抽出できればキーワードリストを簡単に作れるはずと思いまして、抽出方法を探したのですが見つからず、質問するに至った次第です。

"significant_text"を利用する方法のご提案ありがとうございます。
一度こちらの方法で実装してみて、どの程度までいけるのか見てみたいと思います。

significant_text を試してみたのですが、やはりcompletionはできないようですね。
アナライズしてインデックスされているキーワードの抽出方法が分からないので、自力でキーワードリストを生成して、Suggestインデックスに流す込むしかないかと思い始めています。

mkokuiさんの質問でも聞きましたが、「単語群」が何かによるかと。
普通に形態素解析したものでよければ、suggesterの機能を使えば良いですが、
形態素解析された単語が望んでいる単語群でないのであれば、単語群を作成しないといけないかと。

Analyzerによって区切られた単語=望んだものであれば、completionでもうまく行くかと。
古いAPIを利用していますが、参考になる日本語の記事がったので、貼っておきます。
http://d.hatena.ne.jp/Kazuhira/20160213/1455372283

ありがとうございます。

望む「単語群」というのは、まさに「Analyzerによって区切られた単語」です。

サイズが大きめのテキストドキュメントをelasticsearchに登録しまして、このドキュメントがインデックスされる際に形態素解析された単語群を、オートコンプリート機能で利用したいと思っています。

たとえば、上記ご指摘頂いたURLですと、登録するコンテンツが以下となっております。

[
  {
    "content": "吾輩は猫である"
  },
  {
    "content": "我が名は青春のエッセイドラゴン"
  }
]

esに登録される際に、このcontentがアナライズされて
「吾輩」「猫」「我」「名」「青春」「エッセイ」「ドラゴン」と分割されるかと思います。(厳密にはこうではないと思いますが)

この単語群からオートコンプリート(前方一致)を作ろうと思っております。
例えば「エ」と入力すると「エッセイ」の返却が、「ド」と入力すると「ドラゴン」の返却が欲しいというイメージです。

しかし、実際は参考URLにあるように、あるプロパティーに対してcompletionを指定しても、あくまでも形態素解析された単語そのものではなく、content全体に対する前方一致になるため、

  "my-suggest-1" : [ {
    "text" : "我",
    "offset" : 0,
    "length" : 1,
    "options" : [ {
      "text" : "我が名は青春のエッセイドラゴン",
      "score" : 1.0
    } ]
  } ],
  "my-suggest-4" : [ {
    "text" : "わが",
    "offset" : 0,
    "length" : 2,
    "options" : [ {
      "text" : "吾輩は猫である",
      "score" : 1.0
    }, {
      "text" : "我が名は青春のエッセイドラゴン",
      "score" : 1.0
    } ]
  } ],

という結果になってしまいます。

求めたいものは、

  "my-suggest-1" : [ {
    "text" : "ド",
    "offset" : 0,
    "length" : 1,
    "options" : [ {
      "text" : "ドラゴン",
      "score" : 1.0
    } ]
  } ],

という感で、「content」に登録したテキストが形態素解析されてバラバラになった単語のサジェストとなります。
やはり、これには別途indexを作るしかないのかな、と思っていたりするのですが、他に何かアイデアはあったりしますでしょうか・・・。

(そこで、インデックス作成時に解析された単語群を一括で抜き出したいので、そのような方法はありますでしょうか?という質問につながります。)

あー、であれば、単純にTerms Aggregationでfilteringすればいいだけかと。
includeを使えば良いかと。

analyzedなフィールドについてはfielddataを有効になければなりませんが。
https://www.elastic.co/guide/en/elasticsearch/reference/6.2/fielddata.html#_enabling_fielddata_on_literal_text_literal_fields

2 Likes

なるほど!
Terms Aggregationまでは一度試したのですが、「includeを使う」という点までは分かりませんでした。

おっしゃるとおり、includeで正規表現を当てると前方一致・後方一致・LIkEなど色々と表現することができました。
このincludeで解決できそうな気がします。

ありがとうございます。

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.