elasticsearch高亮之詞項向量

無風聽海發表於2022-03-15

一、什麼是詞項向量

詞項向量(term vector)是有elasticsearch在index document的時候產生,其包含對document解析過程中產生的分詞的一些資訊,例如分詞在欄位值中的位置、開始和結束的字元位置、分詞的後設資料payloads等;

term vector是單獨進行儲存的,會額外多佔用一杯的空間,所以elasticsearch預設情況下禁用詞項向量,如果要啟用,我們需要在欄位的mapping中使用term_vector進行設定;

二、term_vector的配置選項

term vector支援以下配置選項

配置選項 描述
no 不啟用term vector,預設值
yes 啟用term vector,但是僅僅記錄分詞
with_positions 啟用term vector, 記錄分詞及分詞在字串中的位置
with_offsets 啟用term vector, 記錄分詞在字串中的起始字元位置
with_positions_offsets 啟用term vector, 記錄分詞在字串中的位置及起始的字元位置
with_positions_payloads 啟用term vector, 記錄分詞在字串中的位置及payloads
with_positions_offsets_payloads 啟用term vector, 記錄分詞在字串中的位置、起始字元位置及payloads

我們使用以下mapping配置,為text、fullname欄位啟用term vector;

PUT /term_vector_test/
{
    "mappings":{
        "_doc":{
            "properties":{
                "text":{
                    "type":"text",
                    "term_vector":"with_positions_offsets_payloads",
                    "store":true,
                    "analyzer":"standard"
                },
                "fullname":{
                    "type":"text",
                    "term_vector":"with_positions_offsets_payloads",
                    "analyzer":"standard"
                }
            }
        }
    },
    "settings":{
        "index":{
            "number_of_shards":1,
            "number_of_replicas":0
        }
    }
}

將以下兩個document傳送到elasticsearch進行index;

PUT /term_vector_test/_doc/1
{
  "fullname" : "John Doe",
  "text" : "twitter test test test "
}

PUT /term_vector_test/_doc/2
{
  "fullname" : "Jane Doe",
  "text" : "Another twitter test ..."
}

三、檢視term vector的資料結構

elasticsearch提供了_termvectors API,我們可以使用它來檢視我們剛才index的doucment產生的term vector;

這個API每次只能檢視特定的某個文件的term vector資訊,我們可以通過url指定具體的document的_id;

term vector主要由term information、term statistics、field statistics構成,其中term information又分成了positions、offsets、payloads三個選項,我們可以通過請求的body的引數分別控制返回的資訊;

下邊我們檢視id=1的文件的text欄位的term vector資訊;

GET /twitter/_doc/1/_termvectors
{
  "fields" : ["text"],
  "offsets" : true,
  "payloads" : true,
  "positions" : true,
  "term_statistics" : true,
  "field_statistics" : true
}

通過返回的資訊可以看到erm vecter由三部分組成

分詞基本資訊

term position,分詞在欄位值中的位置,可以看到分詞test在欄位中佔據下標為1、2、3三個位置,而分詞twitter佔據下標為0的位置;

start and end offsets, 分詞在欄位值中字元開始和結束位置,可以看到分詞twitter的start_offset和end_offset分別為0和7;

term payloads,分詞的後設資料,可以看到每個分詞的payload都是d29yZA==,從這裡可以到elasticsearch預設值為 word;

term frequency,分詞在欄位值中出現的頻率,可以看到分詞twitter的term_freq是 1;

分詞統計資訊

total term frequency,當前分詞在所有文件的當前欄位中出現的頻率,可以看到twitter的ttf是2,test的ttf是4;

document frequency,當前欄位包含當前分詞的文件的數量,可以看到兩個document的text欄位都包含test及twitter,所以兩者的doc_freq為2;

欄位統計資訊

document count, 包含當前欄位的document數量,這裡兩個文件都包含text欄位,所以doc_count為2;

sum of document frequencies,當前欄位中所有分詞對應的document frequency的加和,這裡以下計算可以得到sum_doc_freq為6;

\[df_{sum}(text) = df(test) + df(twitter) + df(anther) + df(...) = 2 + 2 + 1 + 1 = 6 \]

sum of total term frequencies,當前欄位中所有分詞對應的total term frequency的加和,這裡以下計算可以得到sum_ttf為8;

\[tf_{sum}(text) = tf(test) + tf(twitter) + tf(anther) + tf(...) = 4 + 2 + 1 + 1 = 8 \]

{
  "_index" : "twitter",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "took" : 0,
  "term_vectors" : {
    "text" : {
      "field_statistics" : {
        "sum_doc_freq" : 6,
        "doc_count" : 2,
        "sum_ttf" : 8
      },
      "terms" : {
        "test" : {
          "doc_freq" : 2,
          "ttf" : 4,
          "term_freq" : 3,
          "tokens" : [
            {
              "position" : 1,
              "start_offset" : 8,
              "end_offset" : 12,
              "payload" : "d29yZA=="
            },
            {
              "position" : 2,
              "start_offset" : 13,
              "end_offset" : 17,
              "payload" : "d29yZA=="
            },
            {
              "position" : 3,
              "start_offset" : 18,
              "end_offset" : 22,
              "payload" : "d29yZA=="
            }
          ]
        },
        "twitter" : {
          "doc_freq" : 2,
          "ttf" : 2,
          "term_freq" : 1,
          "tokens" : [
            {
              "position" : 0,
              "start_offset" : 0,
              "end_offset" : 7,
              "payload" : "d29yZA=="
            }
          ]
        }
      }
    }
  }
}

基於以下兩點term statistics和field statistics並不是準確的;

刪除的文件不會計算在內;

只計算請求文件所在的分片的資料;

相關文章