Elasticsearch Java客户端如何直接扁平化提取嵌套字段?
解决方案
可以在Elasticsearch搜索阶段直接实现结果扁平化,无需后续JSON转换操作,以下是两种常用方案:
方案一:索引阶段用copy_to预扁平化字段(推荐长期使用)
如果需要长期使用扁平化结构,建议在索引mapping中通过copy_to将嵌套字段复制到顶级字段,这样搜索时直接返回顶级字段,客户端可直接映射到扁平化模型。
1. 定义索引mapping
创建索引时配置copy_to:
{ "mappings": { "properties": { "id": {"type": "keyword"}, "nestedClass": { "type": "object", "properties": { "field1": { "type": "keyword", "copy_to": "field1" }, "field2": { "type": "keyword", "copy_to": "field2" } } }, "field1": {"type": "keyword"}, "field2": {"type": "keyword"} } } }
2. 定义扁平化Model类
public class FlatModel { private String id; private String field1; private String field2; // 生成getter、setter方法 }
3. 搜索请求实现
指定返回扁平化字段,客户端直接映射到FlatModel:
SearchRequest request = SearchRequest.of(s -> s .index("你的索引名") .query(q -> q.matchAll(m -> m)) // 替换为你的查询条件 .source(src -> src.includes("id", "field1", "field2")) ); SearchResponse<FlatModel> response = client.search(request, FlatModel.class);
此方案性能最优,因为扁平化操作在索引时完成,搜索阶段仅需返回预定义字段。
方案二:搜索阶段用脚本动态生成扁平化结构(适合临时需求)
如果无法修改索引mapping,可通过Painless脚本在搜索阶段动态改写返回的_source结构,直接得到扁平化结果。
1. 搜索请求配置脚本
SearchRequest request = SearchRequest.of(s -> s .index("你的索引名") .query(q -> q.matchAll(m -> m)) // 替换为你的查询条件 .source(src -> src .script(script -> script .inline(inline -> inline .source(""" def flatResult = [:]; flatResult.id = ctx._source.id; flatResult.field1 = ctx._source.nestedClass.field1; flatResult.field2 = ctx._source.nestedClass.field2; return flatResult; """) .lang("painless") ) ) ) );
2. 映射到扁平化Model
直接用客户端将结果映射到FlatModel:
SearchResponse<FlatModel> response = client.search(request, FlatModel.class);
此方案无需修改索引,但每次搜索都会执行脚本,性能略逊于方案一,适合临时需求场景。
内容的提问来源于stack exchange,提问作者B. Bal
相关产品推荐
相关产品推荐

