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 思於家中床前