在 Elasticsearch 中,检索选定字段(Retrieve selected fields)是一个重要的功能,用于优化查询性能和减少数据传输量。以下是结合所有回答的详细总结,涵盖每种字段检索方式的原理、应用场景、性能特点以及限制。
1.`_source`参数
`_source`参数允许用户在查询时选择性地返回文档的原始 JSON 数据。Elasticsearch 默认会将整个文档存储在`_source`字段中,你可以通过`_source`参数指定需要返回的字段或排除某些字段。
原理
• 加载`_source`:Elasticsearch 加载整个`_source`字段。
• 解析 JSON:解析`_source`中的 JSON 数据。
• 选择或排除字段:根据`_source`参数中指定的字段路径,选择或排除字段。
• 返回结果:返回过滤后的字段。
适用场景
• 灵活性:适用于需要动态选择字段的场景。
• 部分字段:可以通过`_source`过滤返回部分字段或排除某些字段。
限制
• 需要加载和解析整个`_source`,性能可能较低,尤其是在处理大型文档时。
示例
```json
GET /my-index/_search
{
"query": {
"match_all": {}
},
"_source": ["field1", "field2.*"]
}
```
2.`fields`参数
`fields`参数从索引的映射(mapping)中提取字段值,而不是从`_source`中解析。这种方式通常更高效。
原理
• 查询映射:Elasticsearch 查询索引的映射,了解字段的类型和存储方式。
• 选择数据源:
• 如果字段启用了`doc_values`,则从 doc values 中读取字段值。
• 如果字段未启用`doc_values`,则从`_source`中解析字段值。
• 格式化字段值:支持对日期和地理空间字段进行格式化。
适用场景
• 高效检索:适用于需要高效检索特定字段值的场景。
• 格式化支持:支持对日期和地理空间字段进行格式化。
限制
• 不支持直接检索`text`类型字段的原始值。
• 如果字段未启用`doc_values`,则需要从`_source`中解析字段值,可能会影响性能。
示例
```json
GET /my-index/_search
{
"query": {
"match_all": {}
},
"fields": ["field1", "field2.*"]
}
```
3.`docvalue_fields`参数
`docvalue_fields`参数专门用于从 doc values 中检索字段值。Doc values 是一种列式存储结构,优化了字段值的读取速度,特别适用于排序和聚合操作。
原理
• 列式存储:Doc values 是一种列式存储结构,将字段值以列的形式存储在磁盘上,便于快速读取。
• 直接读取:`docvalue_fields`直接从 doc values 中读取字段值,避免了解析`_source`,从而提高了查询性能。
• 内存映射:为了进一步提高性能,Elasticsearch 会将 doc values 加载到内存中进行操作。
适用场景
• 排序和聚合:适用于需要高效排序或聚合的字段,如`keyword`、`date`、`numeric`等。
• 性能优化:直接从 doc values 中读取,性能更高。
限制
• 不支持`text`类型字段。
• 如果字段未启用`doc_values`,则无法使用`docvalue_fields`。
示例
```json
GET /my-index/_search
{
"query": {
"match_all": {}
},
"docvalue_fields": ["field1", "field2.*"]
}
```
4.`stored_fields`参数
`stored_fields`参数用于检索在映射中明确标记为存储的字段。
原理
• 存储字段:`stored_fields`直接从存储的字段中检索值,这些字段在索引时被标记为`store: true`。
• 避免解析`_source`:与`_source`不同,`stored_fields`不需要加载和解析整个`_source`,因此性能更高。
适用场景
• 存储字段:适用于字段被标记为存储的场景。
• 高效检索:直接从存储中检索字段值,避免了解析`_source`。
限制
• 如果字段未被标记为`store: true`,则无法通过`stored_fields`检索。
• 不支持嵌套字段(`nested`),需要在`inner_hits`中使用。
示例
```json
GET /my-index/_search
{
"query": {
"match_all": {}
},
"stored_fields": ["field1", "field2"]
}
```
5.`script_fields`参数
`script_fields`参数允许通过脚本动态计算字段值。
原理
• 动态计算:`script_fields`使用 Painless 脚本在查询时动态计算字段值。
• 访问`_source`或倒排索引:脚本可以访问`_source`或倒排索引中的字段值。
适用场景
• 动态计算:适用于需要在查询时动态计算字段值的场景。
• 灵活性:可以基于其他字段值进行复杂计算。
限制
• 如果字段未被索引,脚本无法访问这些字段的倒排索引值。
• 脚本计算可能会增加查询的复杂性和执行时间。
示例
```json
GET /my-index/_search
{
"query": {
"match_all": {}
},
"script_fields": {
"calculated_field": {
"script": {
"source": "doc['field1'].value * 2"
}
}
}
}
```
6.无法使用的字段
每种字段检索方式都有其适用范围和限制,以下是一些无法使用的字段类型:
`_source`参数
• 未存储在`_source`中的字段:如果`_source`被禁用(`_source: false`),则无法通过`_source`参数检索任何字段。
`fields`参数
• `text`类型字段:`text`类型字段默认不支持通过`fields`检索,因为它们被分词处理。
• 未索引的字段:如果字段被设置为`index: false`,则无法通过`fields`检索。
• 动态映射禁用的字段:如果动态映射被禁用(`dynamic: false`),未显式定义的字段无法通过`fields`检索。
`docvalue_fields`参数
• `text`类型字段:`text`类型字段不支持 doc values,因此无法通过`docvalue_fields`检索。
• 未启用 doc values 的字段:某些字段类型(如`text`)默认不支持 doc values,即使启用`doc_values: true`,`text`字段仍然无法使用。
`stored_fields`参数
• 未标记为存储的字段:如果字段未被标记为`store: true`,则无法通过`stored_fields`检索。
• 嵌套字段:`stored_fields`不支持直接检索嵌套字段(`nested`),需要在`inner_hits`中使用。
`script_fields`参数
• 未索引的字段:如果字段未被索引,脚本无法访问这些字段的倒排索引值。
• 性能限制:脚本计算可能会增加查询的复杂性和执行时间。
7.字段检索方式的选择指南
根据你的具体需求选择合适的方式,以优化查询性能和资源利用率: