Elasticsearch系列(10)Search之檢索選定的字段

1. 介紹

默認情況下,搜索響應(yīng)中的每個命中文檔都包含字段_source,它是索引文檔時提供的整個JSON對象。為了避免搜索時加載和解析整個_source對象,可以使用以下幾種方式來獲取所選特定字段的值:

  • Doc值字段(Doc value fields)
  • 存儲字段(Stored fields)
  • 源過濾(Source filtering)
  • 腳本字段(Script fields)

2. Doc值字段

可以使用docvalue_fields參數(shù)在搜索響應(yīng)中返回一個或多個字段的doc值,字段的doc值存儲與_source中相同的值,但是doc值存儲在磁盤上基于列的結(jié)構(gòu)中,該結(jié)構(gòu)對排序和聚合進行了優(yōu)化,因為每個字段是單獨存儲的,所以Elasticsearch只讀取請求的字段值,從而避免加載整個文檔_source。

例如,下面的搜索請求使用docvalue_fields參數(shù)來檢索特定字段的doc值,示例如下:

PUT /my_index_01
{
  "mappings": {
    "properties": {
      "content": {
        "type": "text",
        "store": true
      },
      "create_date": { "type": "date" },
      "id": {  "type": "keyword" },
      "user": {
        "properties": {
          "name": { "type": "keyword" },
          "age": { "type": "integer" }
        }
      }
    }
  }
}
POST /my_index_01/_doc/1
{"id":"00000001", "content":"Quick Brown Fox", "create_date": "2015-01-01", "user.name":"james", "user.age": 35}
POST /my_index_01/_doc/2
{"id":"00000002", "content":"Quick White Fox", "create_date": "2015-01-02", "user.name":"fake", "user.age": 26}
GET my_index_01/_search
{
  "query": {
    "match": {
      "content": "Fox"
    }
  },
  "docvalue_fields": [ 
    "id",
    "user*", //1
    {
      "field": "create_date", 
      "format": "epoch_millis" //2
    }
  ],
  "_source": false 
}

注釋1:支持完整字段名和通配符匹配模式。
注釋2:使用object形式,使用格式化參數(shù)來為字段doc值自定義格式,只支持日期字段和數(shù)值字段,日期類型支持日期格式,數(shù)值類型支持DecimalFormat模式。

執(zhí)行結(jié)果如下圖所示:

3. 存儲字段

也可以使用stored_fields參數(shù)在搜索響應(yīng)中包含特定存儲的值,需先在映射中設(shè)置store為true,有選擇地為搜索命中的每個文檔加載特定的存儲字段,例如,只加載字段content的存儲值,示例如下:

GET my_index_01/_search
{
  "query": { "match": { "content": "Fox" } },
  "stored_fields" : ["content"]
}

執(zhí)行結(jié)果片段如下所示:

{
    "_index" : "my_index_01",
    "_type" : "_doc",
    "_id" : "2",
    "_score" : 0.18232156,
    "fields" : {
      "content" : [
        "Quick White Fox"
      ]
    }
}
  • 如果請求的字段沒有被存儲(存儲映射設(shè)置為false),那么它們將被忽略。
  • 只能通過stored_fields選項返回葉子字段,如果指定了一個對象字段,那么它將被忽略。
  • 通常不推薦使用stored_fields。

禁用存儲字段

使用none值可以完全禁用存儲字段(包括元數(shù)據(jù)字段),示例如下:

GET my_index_01/_search
{
  "query": { "match": { "content": "Fox" } },
  "stored_fields": "_none_"
}

4. 源過濾

可以使用_source參數(shù)來選擇返回的源字段,這種叫做源過濾(source filtering)。

如果只返回源字段的子集,請在_source參數(shù)中指定通配符(*)模式。下面的搜索API請求只返回user字段及其屬性的源值:

GET my_index_01/_search
{
  "query": { "match": { "content": "Fox" } },
  "_source": "user.*"
}

可以在_source字段中指定一個數(shù)組。下面的搜索API請求只返回user字段及其屬性、id字段源:

GET my_index_01/_search
{
  "query": { "match": { "content": "Fox" } },
  "_source": ["user.*", "id"]
}

也可以在_source參數(shù)中指定一個對象,該對象包括includes和excludes模式數(shù)組。
includes屬性,表示只返回與其中一個模式匹配的源字段,如果沒有指定includes,則返回整個文檔源數(shù)據(jù)。使用exclude屬性來排除,從滿足includes屬性的文檔中排除exclude中模式匹配的源字段。下面的搜索API請求只返回user字段及其屬性、id字段源,但是需要排除任何有age屬性的字段源:

GET my_index_01/_search
{
  "query": { "match": { "content": "Fox" } },
  "_source": {
    "includes": [ "user.*", "id"],
    "excludes": [ "*.age" ]
  }
}

5. 腳本字段

通過script_fields參數(shù)為每個命中結(jié)果(hit)基于不同的字段進行自定義腳本估算,然后返回腳本計算值。例如,自定義test1、test2、test3三個腳本,示例如下:

GET my_index_01/_search
{
  "query": { "match": { "content": "Fox" } },
  "script_fields": {
    "test1": {
      "script": {
        "lang": "painless",
        "source": "doc['user.age'].value * 2" //1
      }
    },
    "test2": {
      "script": {
        "lang": "painless",
        "source": "doc['user.age'].value * params.factor", //2
        "params": {
          "factor": 2.0
        }
      }
    },
    "test3": {
      "script": {
        "lang": "painless",
        "source": "doc['user.name']" //3
      }
    }
  }
}

注釋1:獲取文檔中user.age字段的值,乘以2
注釋2:獲取文檔中user.age字段的值,乘以參數(shù)params.factor值
注釋3:獲取文檔中user.name字段的值

返回結(jié)果片段如下:

{
  "_index" : "my_index_01",
  "_type" : "_doc",
  "_id" : "2",
  "_score" : 0.18232156,
  "fields" : {
    "test1" : [ 25 ],
    "test2" : [ 52.0 ],
    "test3" : [ "fake" ]
  }
}

腳本字段還可以訪問實際的_source文檔,并通過使用params['_source']提取要從其中返回的特定元素。示例如下:

GET my_index_01/_search
{
   "query": { "match": { "content": "Fox" } },
   "script_fields" : {
      "test1" : {
          "script" : "params['_source']['content']"
      }
    }
}
理解doc['field']與params['_source']['field']
  • 使用doc['field']形式,Elasticsearch會將該字段的詞條加載到內(nèi)存中緩存,這會有更快的執(zhí)行,但也會有更多的內(nèi)存消耗。此外,doc['field']形式中的字段只允許簡單值類型字段(不能返回json對象),并且只對未分析的或基于單詞條的字段有意義。
  • 使用params['_source']['field']形式,Elasticsearch每次使用_source時都必須加載和解析它,這樣使用_source會非常慢,影響執(zhí)行速度。
  • 官方推薦使用doc['field']形式從文檔中訪問值,而不是params['_source']['field']。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容