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

**URL:** <https://discuss.elastic.co/t/topic/126885>\
**Category:** 日本語による質問・議論はこちら\
**Created:** [April 5, 2018, 9:16am UTC](https://discuss.elastic.co/t/topic/126885 "2018-04-05T09:16:29Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![fuyukun](https://avatars.discourse-cdn.com/v4/letter/f/3e96dc/32.png) [@fuyukun](https://discuss.elastic.co/u/fuyukun)\
**Post date:** [April 5, 2018, 9:16am UTC](https://discuss.elastic.co/t/topic/126885/1 "2018-04-05T09:16:30Z")

</div>

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

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

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

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

```

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

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

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

よろしくお願いします。

---

<div class="post-metadata">

**Author:** ![mkokui](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/mkokui/32/28320_2.png) [@mkokui](https://discuss.elastic.co/u/mkokui)\
**Post date:** [April 6, 2018, 3:17am UTC](https://discuss.elastic.co/t/topic/126885/2 "2018-04-06T03:17:15Z")

</div>

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

> [@Analyzeされたワードの一部を取得することはできますか？](https://discuss.elastic.co/t/analyze/121980):
>
> 使用しているのは、Elasticsearch6.2です。 次のようなデータから名詞単語のSuggest機能を作れないか検討しています。 例えば、「役割」というインプット文字列を渡すと、「役割等級」「役割等級制度」というような単語が返ってくるような動きを期待しています。 Elasticsearchの知見がまだまだ浅いため、理解できていないところが多いのですが、 データをPutしたときに下例ですと「質問」に「SampleData」の「質問文字列」、「質問.meishi」にAnalizeされた文字列が入っているものと創造しています。 試行錯誤中に試したやり方ですが、以下のようにaggrigationを実行すると、Bucketの中にAnalizeされた単語が入っていることは確認できました。 GET \_search { "aggs": { "my\_sampler": { "sampler": {"shard\_size": 100 }, "aggs": { "my\_keywords": { "significant\_text": { "field":…

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

> **[Significant text aggregation | Elasticsearch Guide \[master\] | Elastic](https://www.elastic.co/guide/en/elasticsearch/reference/master/search-aggregations-bucket-significanttext-aggregation.html)**

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

```auto
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はまだこちらでも検証段階なので、精度等については調整が必要かと思います。

---

<div class="post-metadata">

**Author:** ![fuyukun](https://avatars.discourse-cdn.com/v4/letter/f/3e96dc/32.png) [@fuyukun](https://discuss.elastic.co/u/fuyukun)\
**Post date:** [April 6, 2018, 8:05am UTC](https://discuss.elastic.co/t/topic/126885/3 "2018-04-06T08:05:15Z")

</div>

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

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

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

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

---

<div class="post-metadata">

**Author:** ![fuyukun](https://avatars.discourse-cdn.com/v4/letter/f/3e96dc/32.png) [@fuyukun](https://discuss.elastic.co/u/fuyukun)\
**Post date:** [April 6, 2018, 10:54am UTC](https://discuss.elastic.co/t/topic/126885/4 "2018-04-06T10:54:37Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![johtani](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/johtani/32/44956_2.png) [@johtani](https://discuss.elastic.co/u/johtani)\
**Post date:** [April 10, 2018, 10:35am UTC](https://discuss.elastic.co/t/topic/126885/5 "2018-04-10T10:35:48Z")

</div>

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

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

---

<div class="post-metadata">

**Author:** ![fuyukun](https://avatars.discourse-cdn.com/v4/letter/f/3e96dc/32.png) [@fuyukun](https://discuss.elastic.co/u/fuyukun)\
**Post date:** [April 10, 2018, 12:31pm UTC](https://discuss.elastic.co/t/topic/126885/6 "2018-04-10T12:31:26Z")

</div>

ありがとうございます。

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

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

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

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

```

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

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

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

```auto
  "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
    } ]
  } ],

```

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

求めたいものは、

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

```

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

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

---

<div class="post-metadata">

**Author:** ![johtani](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/johtani/32/44956_2.png) [@johtani](https://discuss.elastic.co/u/johtani)\
**Post date:** [April 10, 2018, 2:49pm UTC](https://discuss.elastic.co/t/topic/126885/7 "2018-04-10T14:49:44Z")

</div>

あー、であれば、単純に[Terms Aggregation](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html#_filtering_values_3)でfilteringすればいいだけかと。  
`include`を使えば良いかと。

analyzedなフィールドについては`fielddata`を有効になければなりませんが。  
[https://www.elastic.co/guide/en/elasticsearch/reference/6.2/fielddata.html#\_enabling\_fielddata\_on\_literal\_text\_literal\_fields](https://www.elastic.co/guide/en/elasticsearch/reference/6.2/fielddata.html#_enabling_fielddata_on_literal_text_literal_fields)

---

<div class="post-metadata">

**Author:** ![fuyukun](https://avatars.discourse-cdn.com/v4/letter/f/3e96dc/32.png) [@fuyukun](https://discuss.elastic.co/u/fuyukun)\
**Post date:** [April 11, 2018, 8:08am UTC](https://discuss.elastic.co/t/topic/126885/8 "2018-04-11T08:08:41Z")

</div>

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

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

ありがとうございます。

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [May 9, 2018, 8:08am UTC](https://discuss.elastic.co/t/topic/126885/9 "2018-05-09T08:08:49Z")

</div>

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