1. build.gradle 에 추가하기
- elasticsearch 홈페이지에서 repository 정보, dependancy 정보 획득하기
저는 pom.xml 을 사용하지 않고 build.gradle로 라이브러리 관리를 하므로 gradle을 다루겠습니다.
- rest-high-level-client의 repository 정보(gradle)
- rest-high-level-client의 dependency 정보
rest-high-level-client는 rest-client, elasticsearch 가 필요 한 것을 알 수 있습니다.
- rest client의 repository 정보
- rest client의 dependency 정보
rect client의 dependency 에서는 따로 build.gradle에 추가할 것이 없네요 ㅎㅎ
- org.elasticsearch:elasticsearch gradle에 추가하기
https://mvnrepository.com/artifact/org.elasticsearch/elasticsearch/7.14.1
gradle
dependency
dependency 들은 이렇게 나옵니다. 이제 build.gradle에 지금까지 조사한 것들을 추가합니다.
- build.gradle
repositories {
maven {
url "https://snapshots.elastic.co/maven/"
}
maven {
name 'lucene-snapshots'
url 'https://s3.amazonaws.com/download.elasticsearch.org/lucenesnapshots/83f9835'
}
}
dependencies {
//start Es
implementation 'org.elasticsearch:elasticsearch:7.14.1'
implementation 'org.elasticsearch.client:elasticsearch-rest-client:7.14.1'
implementation 'org.elasticsearch.client:elasticsearch-rest-high-level-client:7.14.1'
//end Es
}
2. Configuration 작성
RestHighLevelClient Bean을 사용하기 위해 @Configuration 을 작성합니다.
package spb.configuration;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ElasticSearchConfiguration {
@Value("${elasticsearch.host}")
private String hostname;
@Value("${elasticsearch.port}")
private Integer port;
@Bean
public RestHighLevelClient restHighLevelClient() {
return new RestHighLevelClient(RestClient.builder(new HttpHost(hostname, port, "http")));
}
}
요청을 받을 엘라스틱서치의 ip, port, 프로토콜(http)을 RestClient.builder에 입력하여 인자로 줍니다.
3. Service, ServiceImpl 작성
- SearchService.java
import java.util.List;
import java.util.Map;
public interface SearchService {
public List<Map<String,Object>> sendHighLevelApi(String indexName) throws Exception;
}
검색한 데이터를 Map으로 받아서 List에 담아 return을 하는 방식을 사용하겠습니다. indexName을 param으로 받겠습니다.
- SearchServiceImpl.java
package spb.ubooks.service;
@Service
public class SearchServiceImpl implements SearchService{
@Autowired
RestHighLevelClient client; // Configuration 에서 만든 RestHighLevelClient
@Override
public List<Map<String,Object>> sendHighLevelApi(String indexName) throws Exception {
ArrayList<Map<String,Object>> list = null;
try {
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.size(100); // 검색 결과 가져오는 갯수
searchSourceBuilder.timeout(new TimeValue(60,TimeUnit.SECONDS)); // timeout
searchSourceBuilder.query(QueryBuilders.matchAllQuery()); // 검색(match all 방식, matchAll 말고 다른 여러 방식이 있다. )
searchSourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC)); // score 높은순 (default)
searchSourceBuilder.sort(new FieldSortBuilder("_id").order(SortOrder.ASC)); // id오름차순 정렬
searchRequest.source(searchSourceBuilder); // 설정 적용
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); // resthighlevelclient.search로 검색 요청
SearchHits hits = searchResponse.getHits();
TotalHits totalHits = hits.getTotalHits(); // total 검색 건수
SearchHit[] searchHits = hits.getHits();
list = new ArrayList<Map<String,Object>>();
for (SearchHit hit : searchHits) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap(); // 검색 결과를 Map으로 한건 한건 받아서 list에 추가
list.add(sourceAsMap);
}
}catch (Exception e) {
e.printStackTrace();
}finally {
}
return list;
}
}
4. Controller 에서 호출
@RequestMapping("/complete-works")
public ModelAndView ubooksCompleteWorks() throws Exception {
ModelAndView mv = new ModelAndView("/ubooks/buy/complete-works");
mv.addObject("res",searchService.sendHighLevelApi("combook_*"));
return mv;
}
service에서 만든 sendHighLevelApi에 indexName을 입력하면 검색결과 map을 담은 list가 return됩니다.
view에서 사용할 수 있도록 ModelAndView에 추가합니다.
5. View에서 사용(Thymeleaf)
<div class="col-md-4" th:if="${#lists.size(list)}" th:each="list : ${res}">
<a th:text="${list.title}"></a>
<p th:text="${list.price}"></p>
</div>
res의 건수만큼 반복하는 div를 만들었고, a, p 태그에 th:text를 이용하여 화면에 뿌릴 수 있습니다.
6. 결과 확인
제가 사용하고 있는 bootstrap 템플릿에 결과를 뿌려봤습니다. 성공적으로 뿌려졌습니다 헤헤