Elasticsearch + spirng boot 연동(SELECT)
회사에서 spring boot 에 elasticsearch 7.14 버전을 연동하고 있어 집에서도 실습해보고싶었다.
개발환경: inteli J , java 11 , elasticsearch 7.14.2 , spring boot
일단 간단하게 elasticsearch 에서 테스트로 넣은 index 데이터를 조회해보려고 한다.
ES에서 Spring boot 연동하는 방식은 여러가지 있지만 그중에 직장에서도 사용하고 있는 동일한 방법으로 해봤다.
Java High Level REST Client 방식이다.
High Level REST Client 는 HighLevelRestClient 로 지원하며 엘라스틱 서치에 접근할 때 리퀘스트를 빌더로 만들어서 API 통신 하는 방식이다. 리스폰스도 이미 만들어진 클래스로 받아올 수 있게 지원해준다.
ES 설정 관련 파일 : ElasticsearchConfig.java
@Configuration
public class ElasticsearchConfig {
@Bean
public RestHighLevelClient getRestClient() {
String host = "localhost";
int port = 9200;
return new RestHighLevelClient(RestClient.builder(new HttpHost(host, port, "http" )));
}
}
REST High Level Client 을 사용하여 Elasticsearch 에 클러스터에 대한 검색을 수행하고 검색 결과를 반환 : SearchApi.java
@Slf4j
public class SearchApi {
private RestHighLevelClient client;
public SearchApi(RestHighLevelClient client) {
this.client = client;
}
public SearchResponse search(QueryBuilder qBuilder,int size, String[] indices, String scrollId) {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
return _searchScroll(searchSourceBuilder, qBuilder, size, indices, scrollId);
}
private SearchResponse _searchScroll(SearchSourceBuilder searchSourceBuilder, QueryBuilder qBuilder, int size, String[] indices,
String scrollId) {
final Scroll scroll = new Scroll(TimeValue.timeValueMinutes(1L));
SearchRequest searchRequest = new SearchRequest(indices);
searchSourceBuilder.query(qBuilder);
searchSourceBuilder.size(size);
searchRequest.source(searchSourceBuilder);
searchRequest.scroll(scroll);
searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
SearchResponse response = null;
try {
log.info("Query: " + searchSourceBuilder.toString());
log.info("--Indices: " + Arrays.toString(searchRequest.indices()));
if (scrollId == null || "".equals(scrollId)) {
response = client.search(searchRequest, RequestOptions.DEFAULT);
} else {
SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId).scroll(scroll);
response = client.scroll(searchScrollRequest, RequestOptions.DEFAULT);
}
log.info("--- Response Time(" + response.status() + "): " + response.getTook() + " milliseconds");
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
}
인덱스 조회 : ElasticSearchSample1.java
@Controller
public class ElasticSearchSample1 {
@Autowired
RestHighLevelClient client;
@GetMapping("/items")
public String sample1() throws IOException {
System.out.println("@@@@@@@@@@@@@@@@@@@@@@@ START @@@@@@@@@@@@@@@@@@@");
try {
String scrollId = null;
String[] indices = new String[1];
indices[0] = "items*";
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
boolQueryBuilder.filter(QueryBuilders.termQuery("id", "item1"));
SearchApi searchApi = new SearchApi(client);
SearchResponse response;
response = searchApi.search(boolQueryBuilder, 3000, indices, scrollId);
for (SearchHit hit : response.getHits().getHits()) {
list.add(hit.getSourceAsMap());
}
System.out.println("list @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ : " + list);
for (int j = 0; j < list.size(); j++) {
Map<String, Object> data = list.get(j);
System.out.println("data = " + data.get("id"));
}
}catch(Exception e){
e.printStackTrace();
}finally {
client.close();
}
return "elasticsearch/test";
}
}
현재 ES에 items 인덱스에는 테스트 데이터 1개가 들어있다.
실행결과
조회한 쿼리와 인덱스명, 키바나에서 조회한 동일한 인덱스 데이터를 java에서 확인 할 수 있다.
rangeQuery 를 사용해서 날짜 기간으로 검색 할 수 있다.
sample1 메소드에 아래 내용을 추가한다.
String startDate = "2024-01-01";
String lastDate = "2024-03-01";
boolQueryBuilder.filter(QueryBuilders.rangeQuery("item_date").gte(startDate).lte(lastDate));
gte 는 이상(같거나 큼)
lte 는 이하(같거나 작음) 이란 의미이다.
2024-01-01 보다 같거나 크고 2024-03-01 보다 같거나 작은 데이터를 색인한다.
결과
로그에 생성된 쿼리로 키바나에서 실행해도 동일한 결과가 나온다.
GET items/_search
{"size":3000,"timeout":"60s","query":{"bool":{"filter":[{"range":{"item_date":{"from":"2024-01-01","to":"2024-03-01","include_lower":true,"include_upper":true,"boost":1.0}}}],"adjust_pure_negative":true,"boost":1.0}}}
Reference