ElasticSearch JavaRestClient查询之高亮显示
文章目录
- 一、高亮核心概念
- 二、高亮请求构建
- 1. API结构
- 2. 完整构建示例
- 3. 简化写法
- 三、高亮结果解析
- 1. 解析流程
- 2. 多片段处理
- 四、完整案例实现
- 需求说明:
- Java代码实现:
- 五、关键注意事项
- 1. 字段类型要求
- 2. 搜索结果要求
- 3. 性能优化
- 六、常见问题排查
- 1. 高亮结果为空
- 2. 标签未生效
- 3. 多字段高亮
- 七、扩展功能
- 1. 多种高亮类型
- 2. 匹配片段控制
- 3. 全局标签设置
一、高亮核心概念
- 高亮结果与原始数据分离:
_source
:原始文档数据(无高亮)highlight
:独立的高亮结果字段(带HTML标签)
- 高亮三要素:
- 高亮字段(必须与查询字段一致)
- 前置标签(默认
<em>
) - 后置标签(默认
</em>
)
二、高亮请求构建
1. API结构
SearchRequest request = new SearchRequest("index");
request.source()
.query(...) // 必须包含搜索条件
.highlighter(...); // 设置高亮参数
2. 完整构建示例
// 创建高亮构建器
HighlightBuilder highlightBuilder = new HighlightBuilder();
// 设置高亮字段与标签
highlightBuilder.field("name") // 高亮字段
.preTags("<em>") // 前置标签
.postTags("</em>"); // 后置标签
// 加入请求
request.source().highlighter(highlightBuilder);
3. 简化写法
request.source().highlighter(
new HighlightBuilder()
.field(new HighlightBuilder.Field("name")
.preTags("<strong>")
.postTags("</strong>"))
);
三、高亮结果解析
1. 解析流程
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
// 1. 获取原始数据
String sourceJson = hit.getSourceAsString();
HotelDoc doc = JSON.parseObject(sourceJson, HotelDoc.class);
// 2. 获取高亮数据
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if (highlightFields.containsKey("name")) {
// 3. 提取高亮片段
HighlightField highlightField = highlightFields.get("name");
Text[] fragments = highlightField.getFragments();
String highlightedName = fragments[0].string();
// 4. 替换原始数据
doc.setName(highlightedName);
}
}
2. 多片段处理
// 拼接所有高亮片段
StringBuilder highlightedText = new StringBuilder();
for (Text fragment : fragments) {
highlightedText.append(fragment.string());
}
doc.setName(highlightedText.toString());
四、完整案例实现
需求说明:
- 搜索"脱脂牛奶"
- 对
name
字段进行高亮 - 使用自定义标签
<em>
和</em>
Java代码实现:
@Test
void testHighlight() throws IOException {
// 1. 创建请求对象
SearchRequest request = new SearchRequest("items");
// 2. 构建查询条件
request.source().query(QueryBuilders.matchQuery("name", "脱脂牛奶"));
// 3. 设置高亮参数
HighlightBuilder highlightBuilder = new HighlightBuilder()
.field("name")
.preTags("<em>")
.postTags("</em>");
request.source().highlighter(highlightBuilder);
// 4. 发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 5. 解析结果
parseHighlightResponse(response);
}
private void parseHighlightResponse(SearchResponse response) {
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
// 解析原始数据
ItemDoc doc = JSONUtil.toBean(hit.getSourceAsString(), ItemDoc.class);
// 处理高亮结果
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if (!highlightFields.isEmpty()) {
HighlightField nameField = highlightFields.get("name");
if (nameField != null) {
String highlightedName = nameField.getFragments()[0].string();
doc.setName(highlightedName);
}
}
System.out.println(doc);
}
}
运行结果:
五、关键注意事项
1. 字段类型要求
- 高亮字段必须是
text
类型且包含keyword
子字段 - 错误配置会导致无法获取高亮结果
2. 搜索结果要求
- 必须包含实际搜索条件(如match查询),否则无高亮结果
3. 性能优化
- 避免对长文本字段进行高亮(如
content
字段) - 设置
fragment_size
控制返回片段长度:
highlightBuilder.field("name").fragmentSize(200);
六、常见问题排查
1. 高亮结果为空
- 检查查询条件是否实际匹配文档
- 验证字段映射是否支持高亮
- 检查高亮字段名是否与查询字段一致
2. 标签未生效
- 确认前端HTML转义处理(防止XSS攻击)
- 检查标签是否被CSS样式覆盖
3. 多字段高亮
// 同时高亮多个字段
highlightBuilder
.field("title")
.field("description");
七、扩展功能
1. 多种高亮类型
// 使用不同的高亮器
highlightBuilder
.highlighterType("unified") // 默认高亮器
.highlighterType("plain"); // 简单高亮器
2. 匹配片段控制
highlightBuilder
.numOfFragments(3) // 返回最多3个片段
.noMatchSize(100); // 无匹配时返回前100字符
3. 全局标签设置
// 设置所有字段的默认标签
highlightBuilder
.preTags("<strong>")
.postTags("</strong>");