본문 바로가기

Elastic Stack/Elastic Search

Elastic Search - Spring Boot 연동하기(rest-high-level-client) - 검색 Api 사용하기

1. build.gradle 에 추가하기 

  • elasticsearch 홈페이지에서 repository 정보, dependancy 정보 획득하기 

 

저는 pom.xml 을 사용하지 않고 build.gradle로 라이브러리 관리를 하므로 gradle을 다루겠습니다. 

  - rest-high-level-client의 repository 정보(gradle)

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-getting-started-maven.html

 

Maven Repository | Java REST Client [7.15] | Elastic

The high-level Java REST client is hosted on Maven Central. The minimum Java version required is 1.8. The High Level REST Client is subject to the same release cycle as Elasticsearch. Replace the version with the desired client version. If you are looking

www.elastic.co

 - rest-high-level-client의 dependency 정보

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-getting-started-dependencies.html

 

Dependencies | Java REST Client [7.15] | Elastic

The High Level Java REST Client depends on the following artifacts and their transitive dependencies: org.elasticsearch.client:elasticsearch-rest-client org.elasticsearch:elasticsearch

www.elastic.co

rest-high-level-client는 rest-client, elasticsearch 가 필요 한 것을 알 수 있습니다. 

 - rest client의 repository 정보 

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-low-usage-maven.html

 

Maven Repository | Java REST Client [7.15] | Elastic

The low-level Java REST client is hosted on Maven Central. The minimum Java version required is 1.8. The low-level REST client is subject to the same release cycle as Elasticsearch. Replace the version with the desired client version, first released with 5

www.elastic.co

 - 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 템플릿에 결과를 뿌려봤습니다. 성공적으로 뿌려졌습니다 헤헤