Elasticsearch:fielddata 介紹


默認情況下,大多數字段都已編入索引,這使它們可搜索。 但是,腳本中的排序,聚合和訪問字段值需要與搜索不同的訪問模式。

搜索需要回答“哪個文檔包含該術語?”這個問題,而排序和匯總則需要回答一個不同的問題:“此字段對該文檔的值是什么?”。

大多數字段可以將索引時生產的磁盤doc_values(https://www.elastic.co/guide/en/elasticsearch/reference/current/doc-values.html)用於此數據訪問模式,但是文本(text)字段不支持doc_values。

替代的方案,文本(text)字段使用查詢時內存中的數據結構,稱為fielddata。 當我們首次將該字段用於聚合,排序或在腳本中使用時,將按需構建此數據結構。 它是通過從磁盤讀取每個段的整個反向索引,反轉術語↔︎文檔關系並將結果存儲在JVM堆中的內存中來構建的。

Fielddata針對text字段在默認時是禁用的

Fielddata會占用大量堆空間,尤其是在加載大量的文本字段時。 一旦將字段數據加載到堆中,它在該段的生命周期內將一直保留在那里。 同樣,加載字段數據是一個昂貴的過程,可能導致用戶遇到延遲的情況。 這就是默認情況下禁用字段數據的原因。

假如我們創建一個如下的myindex的索引:

    PUT myindex
    {
      "mappings": {
        "properties": {
          "address": {
            "type": "text"
          }
        }
      }
    }
     
    PUT myindex/_doc/1
    {
      "address": "New York"  
    }

如果您嘗試對文本字段中的腳本進行排序,匯總或訪問值:

    GET myindex/_search
    {
      "size": 20,
      "aggs": {
        "aggr_mame": {
          "terms": {
            "field": "address",
            "size": 5
          }
        }
      }
    }

則會看到以下異常:

顯然,我們不能對text字段進行聚合處理。那么我們該如何處理這個問題呢?

我們的一種方法就是在配置mapping的時候加入"fielddata"=true這個選項。我們來重新對我們的myindex的mapping進行配置:

    DELETE myindex
     
    PUT myindex
    {
      "mappings": {
        "properties": {
          "address": {
            "type": "text",
            "fielddata": true
          }
        }
      }
    }
     
    PUT myindex/_doc/1
    {
      "address": "New York"  
    }
     
    GET myindex/_search
    {
      "size": 0,
      "aggs": {
        "aggr_mame": {
          "terms": {
            "field": "address",
            "size": 5
          }
        }
      }
    }

在這里,我們盡管還是把address這個字段設置為text,但是由於我們加入了"fielddata"=true,那么我們,我們就可以對這個項進行統計了。

與簡單的搜索操作不同,排序和聚合需要能夠發現在特定文檔的特定字段中可以找到哪些術語。 對於這些任務和其他任務,必須具有與Elasticsearch(反向)索引相反的數據結構。 這就是fielddata的目的。

細心的開發者,如果這個時候去Kibana創建一個以myindex為索引的index pattern,我們可以發現:

我們的address字段變為aggregatable,也就是說我們可以對它進行做聚合分析盡管它沒有doc_values。

在啟動fielddata之前

在啟用fielddata之前,請考慮為什么將文本字段用於聚合,排序或在腳本中使用。 這樣做通常沒有任何意義。

在索引之前會分析文本字段,以便可以通過搜索new或york來找到類似New York的值。 當您可能想要一個名為New York的存儲桶時,此字段上的術語匯總將返回一個叫做new存儲桶和一個叫做york存儲桶。

相反,您應該有一個用於全文搜索的文本字段,以及一個為聚合啟用doc_values的未分析的keyword字段,如下所示:

    DELETE myindex
     
    PUT myindex
    {
      "mappings": {
        "properties": {
          "address": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    }

這樣,我們可以使用address來做全文的搜索,而address.keyword被用來做aggregations, sorting 及在腳本中使用。

參考:
【1】https://www.elastic.co/guide/en/elasticsearch/reference/current/fielddata.html
【2】https://qbox.io/blog/field-data-elasticsearch-cluster-instability


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM