1. 程式人生 > >Elasticsearch詞頻統計實現與原理解讀

Elasticsearch詞頻統計實現與原理解讀

0、實戰問題

有了分詞,開發中會遇到,某個索引的文件集合中,共有多少XX關鍵詞?

這就引發出了詞頻統計的問題。

社群問題:

中文分詞後能否統計索引詞頻
初學者,想做一個簡單的論壇檢索和熱詞分析的應用,IK分詞後能否將分好的索引詞出現頻率排序。這樣可以形成一個大致的熱點詞彙範圍。

我知道單條index的話可以用termvectors做這個事情,要是上萬條index能做嗎? 多謝!

1、建立索引

DELETE message_index
PUT message_index
{
   "mappings": {
    "_doc":{
       "properties"
:{ "message": { "analyzer": "ik_smart", "term_vector": "with_positions_offsets", "boost": 8, "type": "text", "fielddata":"true" } } } } }

2、匯入資料

POST message_index/_doc/1
{
  "message"
:"沉溺於「輕易獲得高成就感」的事情:有意無意地尋求用很小付出獲得很大「回報」的偏方,哪怕回報是虛擬的" } POST message_index/_doc/2 { "message":"過度追求“短期回報”可以先思考這樣一個問題:為什麼玩王者榮耀沉溺我們總是停不下來回報" } POST message_index/_doc/3 { "message":"過度追求的努力無法帶來超額的回報,就因此放棄了努力。這點在聰明人身上尤其明顯。以前念本科的時候身在沉溺" }

3、聚合獲取詞頻

POST message_index/_search
{
   "size" : 0,  
    "aggs"
: { "messages" : { "terms" : { "size" : 10, "field" : "message" } } } }

4、返回結果

{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 3,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "messages": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 45,
      "buckets": [
        {
          "key": "回報",
          "doc_count": 3
        },
        {
          "key": "沉溺",
          "doc_count": 2
        },
        {
          "key": "的",
          "doc_count": 2
        },
        {
          "key": "過度",
          "doc_count": 2
        },
        {
          "key": "追求",
          "doc_count": 2
        },
        {
          "key": "一個",
          "doc_count": 1
        },
        {
          "key": "為什麼",
          "doc_count": 1
        },
        {
          "key": "了",
          "doc_count": 1
        },
        {
          "key": "事情",
          "doc_count": 1
        },
        {
          "key": "付出",
          "doc_count": 1
        }
      ]
    }
  }
}

5、核心知識點解讀

“fielddata”:”true” 是什麼?

5.1 基礎認知:text型別不能用於聚合

所有欄位是預設被 indexed(被索引的),這使得它們是可搜尋的.可以在指令碼中排序,聚合和獲取欄位值,但是需要不同的搜尋模式.

搜尋需要回答一個問題 “哪個 document(文件) 包含這個 term(詞條)”,然而排序和聚合需要回答一個不同的問題 ” 這個欄位在這個 document(文件)中的值是多少?”.
text 欄位不支援 doc_values。

引申解析:
1、doc_values是儲存在磁碟的資料結構,在文件建立索引的時候建立。
2、對比:field_data快取主要用於在欄位上進行排序或計算聚合。 它將所有欄位值載入到記憶體中,以便為這些值提供基於文件的快速訪問。

5.2 docvalues和fileddata的本質區別?

docvalues 它儲存某一列的資料,並索引它,用於加快聚合和排序的速度。

fileddata 它儲存某一列的資料,並索引它,用於加快聚合和排序的速度。和docvalues不一樣的是,fielddata儲存的是text型別的欄位分詞後的terms,而不是儲存源欄位資料。

5.3 fileddata的特點

相反,text 欄位使用查詢時存在於記憶體的資料結構 fielddata.這個資料結構是第一次將欄位用於聚合,排序,或者指令碼時基於需求構建的。

它是通過讀取磁碟上的每個 segment(片段)的整個反向索引來構建的,將 term(詞條)和 document(文件)關係反轉,並將結果儲存在記憶體中,在JVM的堆中.

5.4 text欄位預設關閉Fielddat的原因?

text 欄位預設關閉 Fielddata Fielddata會消耗很多堆空間,尤其是載入高基數的 text 欄位的時候.一旦 fielddata 載入到堆中,它在 segment(片段)中的生命週期還是存在的.

此外,載入 fielddata 是一件非常昂貴的過程,會導致使用者體驗到延遲的感覺.這就是為什麼 fielddata 預設關閉.

如果你嘗試對文字欄位上的指令碼進行排序,訪問值,你會看到此異常:

5.5 fielddata的開啟方式?

以下ES6.2.X驗證ok。

PUT my_index/_mapping/_doc
{
  "properties": {
    "my_field": { 
      "type":     "text",
      "fielddata": true
    }
  }
}

2018-05-13 22:58 思於家中床前