日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ElasticSearch评分分析 explian 解释和一些查询理解

發布時間:2024/1/17 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ElasticSearch评分分析 explian 解释和一些查询理解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

ElasticSearch評分分析 explian 解釋和一些查詢理解

按照es-ik分析器安裝了ik分詞器。創建索引:PUT /index_ik_test。索引包含2個字段:content和nick,如下:

GET index_ik_test/_mapping {"index_ik_test": {"mappings": {"fulltext": {"properties": {"content": {"type": "text","analyzer": "ik_max_word"},"nick": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}}}}}} }

實驗環境為:單臺的ElasticSearch6.3.2版本。索引配置如下:

GET index_ik_test/_settings {"index_ik_test": {"settings": {"index": {"creation_date": "1533383757075","number_of_shards": "5","number_of_replicas": "1","uuid": "JajsYmAIT0-uhm-L5xKbeA","version": {"created": "6030299"},"provided_name": "index_ik_test"}}} }

由此可知,ElasticSearch創建索引時,默認為5個primary shard,每個primary shard 一個replica。

在Kibana的Monitoring界面查看:有5個primary shard。其中有5個尚未分配的副本:

為什么有5個尚未分配的副本呢?因為是單節點的ElasticSearch,索引 index_ik_test 的每個primary shard 都有一個副本,而primary shard 與副本 不能在同一臺機器上,由于一共有5個primary shard,故存在著5個尚未分配的副本。

該索引一共存儲著5篇文檔,

GET index_ik_test/fulltext/_search {"query": {"match_all": {}} }

查詢文檔如下:

這5篇文檔中有三篇文檔(文檔id為 5、4、3)包含了 詞 “中國”。由于采用的ik_max_word分詞,因此“其中國家投資了500萬”,是包含“中國”這個詞的。

每個分片中存儲的文檔如下:

其中,shard2代表 分片:[index_ik_test][2]?,shard2上存儲著 doc id為 4和6 的兩篇文檔。shard1 代表分片:[index_ik_test][1],shard1上存儲著 文檔id為 5 的一篇文檔。其它分片存儲的文檔以此類推。(是不是很奇怪我是怎么知道每個分片上存儲具體哪篇文檔的?這是因為:在這個演示環境中,文檔數量少,我是通過不同的查詢詞(比如 通過 query explian "我們",就能知道 doc_6 存儲在shard2上了)進行explian查詢測試得到的。哈哈,知道這個主要是為了后面的 idf 計算分析)

下面以詞 "中國" 為例 來解釋:query explian。執行:

GET index_ik_test/fulltext/_search {"explain": true,"query": {"match": {"content": "中國"}} }

下面從該命令的執行結果詳細分析:

{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 0.5480699,

這表明,查詢請求 scatter 到了所有的 shard (5個shard),其中有3個shard “命中了” 查詢詞 “中國”。這3個shard如下:

"_shard": "[index_ik_test][2]" "_shard": "[index_ik_test][1]" "_shard": "[index_ik_test][4]"

每個shard都會計算一個score,這3個shard中,得分最大的分片是shard2?[index_ik_test][2],它的score是:0.5480699。因此,shard2上的返回結果排在了最前面,只是這里有個小疑問,為什么score返回結果是取最大值(max_score)?

對于 shard[index_ik_test][2]:

"_shard": "[index_ik_test][2]","_node": "7MyDkEDrRj2RPHCPoaWveQ","_index": "index_ik_test","_type": "fulltext","_id": "4","_score": 0.5480699,"_source": {"content": "中國駐洛杉磯領事館遭亞裔男子槍擊 嫌犯已自首"},

文檔id 4 存儲在shard2 上。該文檔針對查詢字符串 “中國” 計算出來的得分是0.5480699。具體的計算細節如下:

"_explanation": {"value": 0.5480699,"description": "weight(content:中國 in 0) [PerFieldSimilarity], result of:","details": [{"value": 0.5480699,"description": "score(doc=0,freq=1.0 = termFreq=1.0\n), product of:","details": [{"value": 0.6931472,"description": "idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:","details": [{"value": 1,"description": "docFreq","details": []},{"value": 2,"description": "docCount","details": []}]},{"value": 0.7906977,"description": "tfNorm, computed as (freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength)) from:","details": [{"value": 1,"description": "termFreq=1.0","details": []},{"value": 1.2,"description": "parameter k1","details": []},{"value": 0.75,"description": "parameter b","details": []},{"value": 8.5,"description": "avgFieldLength","details": []},{"value": 14,"description": "fieldLength","details": []}]}]}]}

0.5480699 由idf 乘以 tfNorm 計算得到。其中 idf=0.6931472,tfNorm=0.7906977

  • idf

    idf由公式?log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5))計算得出。其中,docFreq=1,docCount=2,因為如上面圖所示 :在shard2上,一共有2篇文檔,因此docCount為2,其中只有文檔id為4的這篇文檔包含 "中國" 這個詞,也即:詞 "中國" 出現 在了一篇文檔中,因此docFreq=1。

    不信的話就親自動手算算看。^~^

    我這里有疑問的地方是:這里的 idf 計算公式與官網提到的計算公式有一點不一樣:

后來發現,在ElasticSearch6.3版本之后,字段評分算法默認是BM25算法了。

Elasticsearch allows you to configure a scoring algorithm or similarity per field. The similarity setting provides a simple way of choosing a similarity algorithm other than the default BM25, such as TF/IDF.

在BM25算法的官方文檔API中發現IDF的計算公式如下:

這樣也就知道了,ElasticSearch在計算Term的字段得分是,采用的是BM25算法。計算出該term在這個字段中的idf值后,再結合其他因子(比如tf、字段長度Normalization、文檔長度Normalization)最終得出文檔的Score。

那么tf-idf與BM25的區別是什么?tf-idf是一個term scoring method,而BM25是:給定一個查詢字符串,計算該查詢字符串與文檔之間的得分的一種方法。文檔是由一個個的term組成的,計算文檔得分需要計算文檔中term的得分。將tf-idf結合余弦相似度就是另外一種計算查詢字符串與文檔之間的得分的一種方法。

BM25 is more than a term scoring method, but rather a method for scoring documents with relation to a query. Tf-idf is a term scoring method, which can be incorporated in a document scoring method using a similarity measure (say cosine).

并且BM25的理論基礎是probabilistic retrieval model,而tf-idf的理論基礎是?vector space model。

docFreq=1表示:"中國"這個詞 只在 一篇文檔中出現了。

https://lucene.apache.org/core/7_4_0/core/org/apache/lucene/search/similarities/TFIDFSimilarity.html

docFreq?(the number of documents in which the term?t?appears)

docFreq?- the number of documents which contain the term

docCount?- the total number of documents in the collection

dcoCount=2表示:分片[index_ik_test][2]?里面一共存儲了2篇文檔(即doc_4 和 doc_6)。

  • tfNorm

    tfNorm由公式(freq * (k1 + 1)) / (freq + k1 * (1 - b + b * fieldLength / avgFieldLength))計算。

  • freq ,即termFreq,應該是:term 在該分片下的所有文檔中出現的頻率。在這里,“中國” 在 shard2 的兩篇文檔中,只出現過一次

  • k1 ,這個參數很有意思,默認值為1.2,是用來 平衡 詞頻termFreq 對評分的影響。在傳統的TF評分計算過程中,termFreq越大,計算出來的評分就越大。但是當termFreq大到一定程度時,一般是那種常用詞(或者叫stop words),而這種詞會干擾文檔的評分,因此引入參數 k1 懲罰 termFreq 對評分的影響。要想了解更多,可參考這篇文章:bm25-the-next-generation-of-lucene-relevation。這里也說明,ElasticSearch6.3.2中已經采用了BM25算法作為相關性得分計算公式了。

    https://www.desmos.com/calculator/g8zoebbtvs

  • b,從tfNorm公式可看出:用來調節字段長度對評分的影響。

  • avgFieldLength 值為8.5。為什么是8.5呢?

    在我們的示例中,shard2?[index_ik_test][2]中一共存儲了2篇文檔,一篇是doc_4,它的content字段就是"中國駐洛杉磯領事館遭亞裔男子槍擊 嫌犯已自首"。另一篇是doc_6,它的content字段是"我們的國家"。

    對doc_6的content字段進行分析:

    GET index_ik_test/_analyze {"text": ["我們的國家"],"analyzer": "ik_max_word" } 得到的各個 token 如下: 我們、的、國家 一共3個token

    在下面的第五點fieldLength中,對doc_4的content字段進行分析得到 14個token。

    因此,avgFieldLength = (14+3)/2=8.5。14 是doc_4 content字段分詞之后的token數目;3是doc_6 content字段分詞之后的token數目;2 代表:有兩篇文檔。

    由此可知:avgFieldLength 應該是:shard2分片中 content字段下所有內容 經過 ik_max_word 分詞后的token 總數 除以 shard2里面的文檔數目。

  • fieldLength,長度為14。這個是doc_4 “中國駐洛杉磯領事館遭亞裔男子槍擊 嫌犯已自首” ik_max_word分詞之后的長度。因此,fieldLength指的是 查詢字段(content字段) 被分析(創建索引時指定了 ik_max_word分析器) 之后 的長度。

    GET index_ik_test/_analyze {"text": ["中國駐洛杉磯領事館遭亞裔男子槍擊 嫌犯已自首"],"analyzer": "ik_max_word" }得到的各個token如下: 中國、駐、洛杉磯、領事館、領事、館、遭、亞裔、男子、子槍、槍擊、嫌犯、已、自首 一共 14 個token

    各個參數的值以及計算過程如下:

  • freq=1.0
    k1=1.2
    b=0.75
    avgFieldLength=8.5
    fieldLength=14
    (freq*(k1+1))/(freq+k1*(1-b+b*fieldLength/avgFieldLength))
    0.7906976744186047

    現在,針對shard2,我們已經詳細分析了 tfNorm 和 idf 這兩個參數的計算結果。最終,shard2上的查詢得分為?tfNorm*idf=0.7906977*0.6931472=0.5480699。另外兩個命中 “中國” 的分片的得分計算也類似,就不說了。

由此可看出:ElasticSearch中 tf-idf 的值 是根據單個分片來計算的,也即:以單個的shard為單位來計算 score,更具體地說:當我們講 某 term 一共在 文檔集合中出現了多少次?這個文檔集合指的是:單個分片上存儲的所有文檔。為什么是統計單個分片上的文檔/term 數量呢?這個就要從ElasticSearch的索引方式說起了。這里就簡單地提一下,畢竟這不是本文的重點。

ElasticSearch中有兩個不同Level的索引,一個是:文檔到分片 這個級別的索引,它講的是 數據的分布方式,即決定把哪篇文檔存儲在哪個分片上,這是通過hash文檔ID的方式來實現的。采用hash方式的好處是,ElasticSearch不需要維護文檔的位置信息(boundary),文檔能夠均勻地分布在各個shard上。ElasticSearch采用的哈希函數是:murmur3。

另一個級別的索引是:term 到 文檔的索引,俗稱倒排索引,又稱為:Secondary index。因為我們的查詢需求并不是:給定一個docId,返回這個docId所代表的文檔內容。我們的查詢需求是:給定一個 查詢關鍵詞,找出哪些docId 包含了這個 查詢關鍵詞。因此,要完成這個查詢,第一步是要知道 有哪些docId 包含了 查詢關鍵詞;第二步則是:根據docId,拿到相應的文檔內容。

當文檔的數量很多很多時,一臺機器或者說一個shard都存儲不下這個倒排索引了,因此需要對倒排索引進行分割(partition)。一種分割方式是:Secondary index by Document,另一種是:Secondary index by Term。

  • Secondary index by Document的示意圖如下:(這里的Partition 可以與 ElasticSearch中的 shard 概念等價)

? 這種Secondary Index的分布方式(或者叫數據分布方式,這里的數據當然是倒排索引數據了)是針對每個Partition上的文檔建立一個獨立的Secondary Index(倒排索引)。這種索引方式的好處是:當寫入/更新文檔時,只涉及到該Partition中的倒排索引,而不會修改其他的Partition中的倒排索引內容。

更具體地,以ElasticSearch舉例,因為ElasticSearch就是采用Secondary index by Document。當創建索引時,是默認5個Primary shard,每個Primary shard 一個副本(replica)。Primary shard 就相當于這里的Partition概念。當向ElasticSearch的索引中寫入文檔時,寫請求是請求給某個Primary shard,然后在該Primary shard上構建 倒排索引(posting list),而并不需要修改 其他4個Primary shard 中的倒排索引內容。

each partition is completely separate: each partition maintains its own secondary indexes, covering only the documents in that partition. It doesn’t care what data is stored in other partitions.

? 因此,查詢的時候,需要將查詢請求發送到每一個partition(shard)。為什么呢?因為當我們查詢的時候,一般是輸入某個詞進行查詢,比如輸入"中國"進行查詢,而由于Elasticsearch采用 secondary index by document 這種方式,各個shard 維護著自己的 secondary index,比如,在文檔1 中 包含了 "中國" 這個詞,而文檔1 被哈希分片到 shard1中存儲;文檔2也包含了"中國" 這個詞,但是文檔2可能被哈希到另外一個shard,比如shard2上存儲……因此,所有包含"中國" 這個詞的文檔 可能分布在 Elasticsearch的所有分片中,因此查詢請求需要分發到每個shard上去,這就是所謂的Scatter 查詢。當然了,由于primary shard可以設置若干個 replica,因此,將查詢請求分發到 replica上,通過 replica 來扛 大量的查詢請求。畢竟 index操作(將文檔寫入Elasticsearch)是由primary shard處理的,那將查詢請求交由 replica處理,一定程度上緩解了primary shard的壓力。

  • Secondary index by Term示意圖如下:

? 這種Secondary index的分布方式 是按”范圍“ 來進行分布,關于數據的分布方式,可參考:[分布式系統原理介紹。比如說,對于 color 這個字段,顏色有 black、red、silver……文檔中 顏色范圍首字母為 [a-r] 的那些docId 存儲在 Partition0 分片上。而所有 顏色范圍首字母 [s-z] 的docId,則存儲在Partition1分片上。 采用這種分布方式的倒排索引,一篇文檔中的不同字段 可能會在 多個Partition的字段中被索引。比如,文檔893 的color 字段的內容是 silver,它在Partition1中被索引了;而文檔893的make字段內容是Audi,它在Partition0中被索引了。這種索引方式的缺點顯而易見:當更新/插入一篇文檔時,有可能需要更新多個Partition中的倒排索引內容。 因此,查詢的時候,可以只將查詢請求發送到某個特定的partition(shard)。

以上內容,全是自己的理解。可能會有很多不嚴謹的地方。

補充說明
這篇文章記錄的文檔得分計算比較簡單:1,它只涉及到 單個字段查詢,即只查詢content字段;2,查詢字符串只有一個term,即:“中國”。
而現實中的查詢,查詢字符串可能包含多個term,并且針對索引中的多個字段查詢。因此,文檔得分的計算要復雜得多。

參考文獻:

  • 分布式系統原理介紹
  • bm25-the-next-generation-of-lucene-relevation
  • TFIDFSimilarity
  • ElasticSearch采用的hash函數
  • 【Elasticsearch】打分策略詳解與explain手把手計算

最后,放一份完整的explian 查詢分析 返回內容:

原文:https://www.cnblogs.com/hapjin/p/9677753.html

總結

以上是生活随笔為你收集整理的ElasticSearch评分分析 explian 解释和一些查询理解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。