@Mapping, @Setting
Mapping의 경우 입력 값의 매핑 정보(_mapping)을, Setting의 경우 인덱스 설정 정보인 분석기 정보를 집어넣었다.
nori 분석기의 경우 이미 elasticsearch에서 받아 적용해놓은 상태임을 유의할 것.
이후 간단한 저장 작업이 동작됨을 확인할 수 있었다. 기존의 JPA와 크게 다르지는 않다.
@Query 사용
참조 블로그 :
JPQL(JPA) 처럼 JSON으로 쿼리문을 조합해서 사용할 수 있는 듯 하다.
한번 테스트해보자.
JPA처럼 사용할 수 있는 기능이 몇 개 있는 모양이다.
- Repository 인터페이스: Spring Data Elasticsearch에서는 ElasticsearchCrudRepository나 ElasticsearchRepository 인터페이스를 상속받아 사용한다. 이를 통해 기본 CRUD 작업을 수행할 수 있다.
- 쿼리 메소드: JPA처럼 메소드 이름으로 쿼리를 정의할 수 있다. 예를 들면, **findByName(String name)**이나 findByNameAndAge(String name, Integer age) 같은 메소드를 정의하면, 해당 필드를 기준으로 검색을 수행한다.
- @Query 어노테이션: @Query 어노테이션을 사용하면 Elasticsearch의 JSON 쿼리를 직접 작성해서 사용할 수 있다. 이를 통해 매치 쿼리, 텀 쿼리, 불리언 쿼리 등 복잡한 쿼리도 작성 가능하다.
- Criteria API: Spring Data Elasticsearch는 Criteria API도 제공한다. 이를 사용하면 프로그래밍 방식으로 쿼리를 구성할 수 있다.
이 중 @Query로 직접적으로 확인해보겠다.
https://codebeautify.org/jsonminifier
해당 사이트에서 JSON 타입으로 쿼리문을 변경할 수 있다.
이를 적용해보자.
//?0, ?1 등의 플레이스홀더는 Spring Data의 쿼리 메소드에서 매개변수를 참조할 때 사용하는 방식이다.
//?0은 첫 번째 매개변수, ?1은 두 번째 매개변수를 참조
@Query("{\"query\":{\"match\":{\"accommodation_name\":\"?0\"}}}")
List<Accommodation> querytest(String name);
//원래 키바나 콘솔에서는 다음과 같았음.
GET test_logstash_accommodations/_search
{
"query": {
"match": {
"accommodation_name": "경상문경청산펜션"
}
}
}
에러 : 'ElasticsearchException, [type=named_object_not_found_exception, reason=[1:10] unknown field [query]]'
저렇게 쿼리를 짜도 실제 나가는 값은 :Request body: {"from":0,"size":0,"query":{"wrapper":{"query":"eyJxdWVyeSI6eyJtYXRjaCI6eyJhY2NvbW1vZGF0aW9uX25hbWUiOiLqsr3sg4HrrLjqsr3ssq3sgrDtjpzshZgifX19"}},"version":true,"explain":false,"track_total_hits":2147483647} , 이렇게 나간다.
Elasticsearch의 wrapper 쿼리는 Base64 인코딩된 쿼리를 감싼 형태로 사용되는데, 여기서는 Spring Data Elasticsearch가 @Query에 제공된 JSON 쿼리를 Base64로 인코딩하고 wrapper 쿼리로 감싸서 Elasticsearch에 전달하는 것으로 보인다.
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-wrapper-query.html
몇시간째 왜 안 되나 고민하는 도중, query를 빼니 동작하는 것을 확인하였다..
이 부분은 이해가 잘 되지 않지만, 다음과 같은 이유라고 한다.
wrapper가 붙는 문제는 Spring Data Elasticsearch가 @Query 애노테이션을 해석할 때 발생하는 것으로 보입니다. 이를 해결하려면 다음과 같은 방법을 시도해 볼 수 있습니다:
@Query 애노테이션 대신 메소드 이름을 이용한 쿼리 생성 방법을 사용하면, 내부적으로 wrapper 없이 쿼리를 생성합니다.
다른 방법
Custom Repository 사용하기: Custom Repository를 사용하여 직접 RestHighLevelClient로 쿼리 실행을 수행한다.
public interface CustomAccommodationRepository {
List<Accommodation> customQuery(String accommodationName);
}
@Repository
public class CustomAccommodationRepositoryImpl implements CustomAccommodationRepository {
private final RestHighLevelClient client;
@Autowired
public CustomAccommodationRepositoryImpl(RestHighLevelClient client) {
this.client = client;
}
@Override
public List<Accommodation> customQuery(String accommodationName) {
// RestHighLevelClient를 사용하여 직접 쿼리 실행
// ...
}
}
NativeSearchQueryBuilder 사용하기: NativeSearchQueryBuilder를 사용하여 Elasticsearch 쿼리를 직접 생성하고 실행한다.
@Autowired
private ElasticsearchRestTemplate elasticsearchTemplate;
public List<Accommodation> searchWithNativeQuery(String accommodationName) {
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery("accommodation_name", accommodationName))
.build();
return elasticsearchTemplate.queryForList(searchQuery, Accommodation.class);
}
Wrapper 쿼리를 직접 사용하기: Wrapper 쿼리의 동작을 이용하려면 쿼리를 Base64 인코딩된 문자열로 전환하여 사용할 수 있을 것이다.
이 중 NativeQuery를 사용해보기로 했다.
https://juntcom.tistory.com/149
https://www.baeldung.com/spring-data-elasticsearch-queries
'프로젝트 > 여행지 오픈 API' 카테고리의 다른 글
[ElasticSearch] spring data elasticsearch Null 출력 이슈(Getter, Reflection) (1) | 2023.11.03 |
---|---|
[ElasticSearch] 로그스태시 최종 삽입 (0) | 2023.11.02 |
[ElasticSearch, LogStash] LogStash로 csv 파일 적재 (0) | 2023.10.31 |
[ElasticSearch] Nori 분석기, 오타 보정(fuzzy), 로그스태시(logStash) (0) | 2023.10.30 |
[ElasticSearch] 엘라스틱서치 - Springboot 연동 (2) | 2023.10.30 |