Elastic Stack应用宝典
上QQ阅读APP看书,第一时间看更新

4.3 字段投影

投影(Projection)的概念源于关系型数据库,是指从一个关系中选取若干个属性形成一个新的关系。简单来说,就是在查询表时不将所有字段返回,而只返回其中的部分字段。Elasticsearch并没有直接引入投影的概念,但支持类似投影的操作。这主要体现在对查询结果的_source字段和fields字段的定制上。

4.3.1 _source参数

在第2章2.2.2节中曾经介绍过,Elasticsearch文档查询结果中会包含_source元字段,这个字段存储了文档的最原始数据。_search接口提供了_source参数,可以定制源文档中哪些字段出现中_source中。这个参数可以在URI中使用,也可以在请求体中使用。例如在示例4-14中,_source将只包含DestCountry字段的值:

示例4-14 _source参数

如果需要返回多个字段,可以使用数组设置_source,并且可以使用通配符星号“*”。例如下面两个请求,都将返回OriginCountry和DestCountry字段:

示例4-15 使用数组和星号

当然,使用星号匹配的范围更大一些,如果索引中包含其他以Country结尾的字段,它们也将出现在返回结果中。类似地,_source也可以设置为false,这将禁止在返回的结果中包含_source源文档内容,而只包含元字段。除此之外,还可以在_source字段中添加includes和excludes字段,以明确包含和排除字段。例如在示例4-16中,将所有包含lon、lat等经纬度信息的字段包含进来,而又排除了DestLocation的子字段,所以在返回的结果中应该只包含OriginLocation:

示例4-16 includes和excludes

4.3.2 stored_fields参数

除了使用_source字段过滤可以出现在源文档中的字段以外,还可以使用stored_fields字段指定哪些被存储的字段出现在结果中。当然这些字段的store属性要设置为true,否则即使在stored_fields中设置了它们,也会被忽略。例如,在示例4-17中,author字段的store参数为true而title设置为false,则在查询的结果中将忽略title:

示例4-17 stored_fields

在返回结果中会增加一个fields字段,其中包含了stored_fields中配置的字段值。此外,在使用stored_fields之后,_source字段默认将不会出现在结果中,但可通过将_source参数设置为true让它返回。字段的store参数在本书第2章2.2.2节也有过介绍,当文档某字段单独使用的频率比较高而其他字段值占用空间又非常大时,就可以把这种常用的字段单独保存起来使用。

4.3.3 docvalue_fields参数

docvalue_fields也是_search接口的参数,它用于将文档字段以文档值机制保存的值返回。文档值机制是非text类型字段支持的一种在硬盘中保存字段原始值的机制,可通过字段的doc_value参数设置开启或关闭。这种机制也是在本书第2章2.2.2节讲解,详细介绍请参考该章节。

示例4-18 docvalue_fields

在示例4-18中,docvalue_fields接收的对象有两个属性,field定义字段名称,而format则定义数值和日期的格式。在示例中使用了日期格式epoch_millis,所以返回结果将以毫秒数显示timestamp字段。format可以使用use_field_mapping关键字,它代表的含义是使用字段在索引映射中定义的格式。类似于stored_fields,docvalue_fields查询的返回结果中也会增加一个fields字段,其中包含了在docvalue_fields中声明的字段及其文档值。与stored_fields不同的是,docvalue_fields的返回结果中默认会包含_source字段。所以在示例4-18中使用_source参数过滤了返回结果以保证_source中也只包含timestamp字段。

4.3.4 script_fields参数

script_fields同样是_search接口的参数,它可以通过脚本向检索结果中添加字段。与stored_fields和docvalue_fileds类似,通过脚本添加的字段也会出现在结果的fields字段中。默认情况下,使用了script_fields参数后,_source字段也不会出现在返回结果中,但可使用_source参数配置开启。例如在示例4-19中向返回结果添加了price_per_km字段,它通过AvgTicketPrice字段和DistanceKilometers字段相除而得,反映了机票每公里的平均票价:

示例4-19 script_fields

script_fields中默认使用的脚本也是Painless,可以在这个上下文中使用的变量见表4-3。

表4-3 script_fields可使用脚本变量