kok202
엘라스틱 서치 Rest Client

2019. 3. 20. 20:37[개발] 기록/오늘의 고민

해결

1. 엘라스틱 서치 템플릿을 안쓰는 방향으로 하였다.

2. 엘라스틱 서치 (유사) JPA 를 안사용 하는 방향으로 하였다.

3. 엘라스틱 서치를 Rest api로 호출하기로 하였다.

=> 엘라스틱 서치는 자바에서 Rest api 로 엘라스틱 서치를 호출 할 수 있도록 2가지 형태로 지원한다.

=> 1. Low level REST Client

=> 2. High level REST Client

=> Low level REST Client 는 RestClient 로 지원하며 엘라스틱 서치에 REST API로 접근하는 방식이다.

=> High level REST Client 는 HighLevelRestClient 로 지원하며 엘라스틱 서치에 접근할 때 리퀘스트를 빌더로 만들어서 API 통신 하는 방식이다. 리스폰스도 이미 만들어진 클래스로 받아올 수 있게 지원해준다.

=> High level REST Client 는 Low level REST Client 을 이용하여 구현되어있다고 공식 문서에 나와있다.

=> 참조할만한 포스트

0. 공식문서

1. (2018.07) KWANGSIK LEE's log

2. (2018.03) ES 5 -> ES 6

3. (2017.11) 이케이님

=> 모듈에대한 의존성이 더 낮고 API 의 body를 직접 제어할 수 있는 Low level REST Client 를 쓰기로 하였다.





장점

1. @Document에서 자유로워지니 인덱스 생성이 자유로워졌다.

2. @Document에서 자유로워지니 데이터 삽입도 자유로워졌다.

3. 인덱스 생성 ~ 맵핑 파일 적용이 하나의 api 호출로 합쳐져서 인덱스만 성공하고 맵핑은 실패할 수도 있다는 걱정거리가 사라졌다. (Put 인덱스 할때 맵핑정보도 넘기면 되므로)






새로 나온 문제상황과 해결

- 해쉬 데이터를 엘라스틱 서치에 저장해야한다.

=> 안타깝게도 엘라스틱 서치는 해쉬라는 데이터 타입이 존재하지않는다.

=> Nested 방식으로 임의의 자료형을 맵핑하는 방식이 존재

=> 맵핑 정보를 만들 때 엔티티 멤버 변수의 타입을 알아내서 HashMap이면 nested 데이터 타입으로 지정해주자.


엘라스틱 서치에 저장하려는 엔티티

 @Data

 public class MyData{

 String myName;

 HashMap<String, String> myHashs;

 }


엘라스틱 서치 맵핑 정보

 {

"mappings" : {

"_doc" : {

"properties" : {

"myName" : { 

"type" : "text" 

},

"myHashs" : {

"type":"nested",

"properties : {

"key" : "text",

"value" : "text"

}

}

}

}

 }


Json 데이터를 insert 하려는 형식

 { 

"myName" : "kok202",

"myHashs": 

[{"key":"abc", "value":"123"},

{"key":"def", "value":"456"},

{"key":"ghi", "value":"789"}]

 }


=> 해쉬 데이터를 Jackson으로 그대로 파싱하면

 { 

"myName" : "kok202",

"myHashs": 

[{"abc","123"},

{"def","456"},

{"ghi","789"}]

 }

다음과 같이 파싱된다.

해쉬맵을 원하는 방식으로 Serialize, Deserialize 해주는 커스텀 Serializer, Deserializer 를 만들어야한다.

그리고 해쉬 데이터 필드 위에 해당 어노테이션을 달아주는 방식으로 해결하였다.

@JsonSerializer

@JsonDeserializer






* 변수 타입을 알아내기 위해 커스텀 어노테이션을 만들어서 사용했는데 이제 크게 의미 없으니 다 지우자.


* mapping 정보가 해쉬맵 때문에 어쩔수 없이 엔티티에 의존적이다 = 맵핑 파일을 만드는 것이 자동화가 불가능하다. 

=> 이럴거면 그냥 스트링으로 json 파일을 만들어서 때려박을걸 그랬다.


* ElasticsearchTemplate은 Spring 쪽에서 지원하는 Spring-data-elasticsearch 에서 사용하는 것이다.

* Low, High level REST API 는 Elasticsearch 쪽에서 지원하는 공식 api 이다.

=> 아예 ElasticsearchTemplate를 사용하지 말자

=> spring-boot-starter-data-elasticsearch 디펜던시를 삭제할 수 있다.