Elasticsearch系列(10)Search之检索选定的字段

1. 介绍

默认情况下,搜索响应中的每个命中文档都包含字段_source,它是索引文档时提供的整个JSON对象。为了避免搜索时加载和解析整个_source对象,可以使用以下几种方式来获取所选特定字段的值:

  • Doc值字段(Doc value fields)
  • 存储字段(Stored fields)
  • 源过滤(Source filtering)
  • 脚本字段(Script fields)

2. Doc值字段

可以使用docvalue_fields参数在搜索响应中返回一个或多个字段的doc值,字段的doc值存储与_source中相同的值,但是doc值存储在磁盘上基于列的结构中,该结构对排序和聚合进行了优化,因为每个字段是单独存储的,所以Elasticsearch只读取请求的字段值,从而避免加载整个文档_source。

例如,下面的搜索请求使用docvalue_fields参数来检索特定字段的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形式,使用格式化参数来为字段doc值自定义格式,只支持日期字段和数值字段,日期类型支持日期格式,数值类型支持DecimalFormat模式。

执行结果如下图所示:

3. 存储字段

也可以使用stored_fields参数在搜索响应中包含特定存储的值,需先在映射中设置store为true,有选择地为搜索命中的每个文档加载特定的存储字段,例如,只加载字段content的存储值,示例如下:

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

执行结果片段如下所示:

{
    "_index" : "my_index_01",
    "_type" : "_doc",
    "_id" : "2",
    "_score" : 0.18232156,
    "fields" : {
      "content" : [
        "Quick White Fox"
      ]
    }
}
  • 如果请求的字段没有被存储(存储映射设置为false),那么它们将被忽略。
  • 只能通过stored_fields选项返回叶子字段,如果指定了一个对象字段,那么它将被忽略。
  • 通常不推荐使用stored_fields。

禁用存储字段

使用none值可以完全禁用存储字段(包括元数据字段),示例如下:

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

4. 源过滤

可以使用_source参数来选择返回的源字段,这种叫做源过滤(source filtering)。

如果只返回源字段的子集,请在_source参数中指定通配符(*)模式。下面的搜索API请求只返回user字段及其属性的源值:

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

可以在_source字段中指定一个数组。下面的搜索API请求只返回user字段及其属性、id字段源:

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

也可以在_source参数中指定一个对象,该对象包括includes和excludes模式数组。
includes属性,表示只返回与其中一个模式匹配的源字段,如果没有指定includes,则返回整个文档源数据。使用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参数为每个命中结果(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字段的值,乘以参数params.factor值
注释3:获取文档中user.name字段的值

返回结果片段如下:

{
  "_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会将该字段的词条加载到内存中缓存,这会有更快的执行,但也会有更多的内存消耗。此外,doc['field']形式中的字段只允许简单值类型字段(不能返回json对象),并且只对未分析的或基于单词条的字段有意义。
  • 使用params['_source']['field']形式,Elasticsearch每次使用_source时都必须加载和解析它,这样使用_source会非常慢,影响执行速度。
  • 官方推荐使用doc['field']形式从文档中访问值,而不是params['_source']['field']。

你可能感兴趣的:(Elasticsearch系列(10)Search之检索选定的字段)