Spring Boot - ElasticSearch RestHighLevelClient 검색 결과 하이라이팅 (HighlightBuilder)
RestHighLevelClient의 HighlightBuilder를 이용하여 검색 결과를 하이라이팅 처리해보겠습니다.
Map<String,Object> resultMap = new HashMap<String,Object>();
try {
SearchRequest searchRequest = new SearchRequest("combook*"); // 인덱스명
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.size(10000);
searchSourceBuilder.timeout(new TimeValue(60,TimeUnit.SECONDS));
searchSourceBuilder.query(QueryBuilders.matchQuery("title", "지구별")); // title 필드 검색
searchSourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC)); // score 높은순 (default)
HighlightBuilder highlightBuilder = new HighlightBuilder();
HighlightBuilder.Field highlightTitle = new HighlightBuilder.Field("title");
highlightTitle.highlighterType("unified"); // unified : 통일(default)
highlightBuilder.field(highlightTitle);
searchSourceBuilder.highlighter(highlightBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); // 검색 요청
SearchHits hits = searchResponse.getHits();
TotalHits totalHits = hits.getTotalHits(); // total 검색 건수
SearchHit[] searchHits = hits.getHits();
List<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
list = new ArrayList<Map<String,Object>>();
for (SearchHit hit : searchHits) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap(); // 검색 결과를 Map으로 한건 한건 받아서 list에 추가
HighlightField field = hit.getHighlightFields().get("title");
sourceAsMap.put("highlight", field);
list.add(sourceAsMap);
}
resultMap.put("totalHits", totalHits.value);
resultMap.put("searchResults", list);
}catch (Exception e) {
e.printStackTrace();
resultMap.put("totalHits", -500);
resultMap.put("exception", e);
}
return resultMap;
searchSourceBuilder.query(QueryBuilders.matchQuery("title", "지구별")); 은 title 필드에서 "지구별" 키워드로 검색을 합니다.
하이라이팅을 설정하는 부분입니다.
HighlightBuilder highlightBuilder = new HighlightBuilder();
HighlightBuilder.Field highlightTitle = new HighlightBuilder.Field("title"); // 하이라이팅 하는 필드명을 설정합니다.
highlightTitle.highlighterType("unified"); // unified : 통일(default) // 하이라이팅 타입을 설정합니다. unified 뿐만 아니라 plain, fvh 옵션을 사용할 수 있습니다.
highlightBuilder.field(highlightTitle); // highlightTitle을 highlightBuilder에 적용시킵니다.
searchSourceBuilder.highlighter(highlightBuilder); // 설정이 적용된 highlightBuilder를 searchSourceBuilder에 반영합니다.
검색 결과를 가져옵니다.
for (SearchHit hit : searchHits) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap(); // 검색 결과를 Map으로 한건 한건 받아서 list에 추가
HighlightField field = hit.getHighlightFields().get("title"); // 하이라이팅 결과 접근
sourceAsMap.put("highlight", field); // 하이라이팅 결과 맵에 추가하기
list.add(sourceAsMap);
}
결과 확인
{
"totalHits": 1,
"searchResults": [
{
"images": "/images/88.jpg|/images/89.jpg|/images/90.jpg",
"list_price": 180000,
"book_id": 60,
"title": "지구별 신화여행",
"max_age": "10",
"shipping_fee": "0",
"reg_date": "20210930000000",
"new_or_used": "u",
"highlight": {
"name": "title",
"fragments": [
{
"fragment": true
}
],
"fragment": true
},
"@timestamp": "2021-11-22T12:49:02.121Z",
"seller_name": "달콤하게v (개인사업자)",
"pub_year": null,
"price": 40000,
"@version": "1",
"publisher": "한국삐아제",
"seller_contact": "010-3333-8888",
"state": "전30권,깨끗합니다 사진으로 보세요~",
"updated_date": null,
"department": "역사/유사",
"min_age": "5",
"seller_id": "admin"
}
]
}
highlight 부분에 우리가 원하는 하이라이팅 결과가 포함되어 있지 않습니다. 다시 소스단으로 넘어가서 해결을 해봅시다.
for (SearchHit hit : searchHits) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap(); // 검색 결과를 Map으로 한건 한건 받아서 list에 추가
HighlightField field = hit.getHighlightFields().get("title");
sourceAsMap.put("hl_name", field.getName());
Text[] t = field.getFragments();
sourceAsMap.put("hl_fragments", t[0]);
sourceAsMap.put("hl_toString", t[0].toString());
list.add(sourceAsMap);
}
결과 확인
{
"totalHits": 1,
"searchResults": [
{
"images": "/images/88.jpg|/images/89.jpg|/images/90.jpg",
"hl_name": "title",
"hl_fragments": {
"fragment": true
},
"list_price": 180000,
"book_id": 60,
"title": "지구별 신화여행",
"max_age": "10",
"shipping_fee": "0",
"reg_date": "20210930000000",
"new_or_used": "u",
"@timestamp": "2021-11-22T12:49:02.121Z",
"seller_name": "달콤하게v (개인사업자)",
"pub_year": null,
"price": 40000,
"@version": "1",
"hl_toString": "<em>지구별</em> 신화여행",
"publisher": "한국삐아제",
"seller_contact": "010-3333-8888",
"state": "전30권,깨끗합니다 사진으로 보세요~",
"updated_date": null,
"department": "역사/유사",
"min_age": "5",
"seller_id": "admin"
}
]
}
hl_toString 에 원하는 결과가 도출되었습니다.