Blog

[Spring][258] Elasticsearch APIs

Category
Author
Tags
PinOnMain
1 more property
JPQL 쿼리로 직접 검색 방식 정하기
@Repository public interface ElasticBookSearchRepository extends ElasticsearchRepository<ElasticsearchBook, Long>, ElasticCustomBookSearchRepository { // 이건 개발자가 직접 연산부를 작성하는 방식임 // 제어권이 개발자에 있음 //List<ElasticsearchBook> findByBookNameContains(String keyword); // Elasticsearch API의 쿼리문을 작성해서 변경해보는 방법 // 이건 제어권이 Spring Data Elasticsearch 에 있음 // 쿼리를 SPE가 분석함 //QueryStringQuery - 엘라스틱서치 내장 기본 쿼리 @Query("{\"query_string\": {\"query\": \"?0\"}}") List<ElasticsearchBook> findByQueryStringQuery(String queryString, Pageable pageable); //조건검색(bool) //@Query("{\"bool\": {\"must\": {\"query_string\": {\"query\": \"?0\"}}}}") //List<ElasticsearchBook> findByQueryStringQuery(String queryString, Pageable pageable); /* must: [필드] AND [컬럼] = [조건] must_not: [필드] AND [컬럼] != [조건] should: [필드] OR [컬럼] = [조건] filter: [필드] [컬럼] IN ( [조건] ) */ }
Java
복사
아래 쿼리를 @Query 어노테이션을 통해서 작성하여 검색의 방식을 변경 할 수 있다. 기존 직접 내부 로직을 구성하는 방식과 다르게, 마치 JPQL을 사용하는것 처럼 쿼리문을 작성 할 수 있다. 그럼 마찬가지로 쿼리문이 컴파일 단계에서 검사되지 않는 단점이 있을 것으로 보여진다.
QueryDSL로 구현해보기
build.gradle 의존성 추가
dependencies { implementation 'com.querydsl:querydsl-apt:4.x.x' implementation 'com.querydsl:querydsl-elasticsearch:4.x.x' }
Java
복사
QueryDSL 플러그인 및 태스크 설정
plugins { id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" } querydsl { jpa = false querydslSourcesDir = 'src/main/generated' } sourceSets { main { java { srcDir 'src/main/generated' } } } configurations { querydsl.extendsFrom compileClasspath } compileQuerydsl { options.annotationProcessorPath = configurations.querydsl }
Java
복사
ElasticBookRepository를 상속받은 ElasticBookSearchRepositoryImpl.java 구현체에서 다음처럼 구현한다. Q객체를 통해서 쿼리팩토리를 통해 쿼리를 메소드형태로 작성하게 된다. 이러면 컴파일 단계에서 개발자의 오류를 찾을 수 있다.
import com.querydsl.core.types.dsl.StringPath; import com.querydsl.elasticsearch.ElasticsearchQuery; import com.querydsl.elasticsearch.ElasticsearchQueryFactory; public class ElasticBookSearchRepositoryImpl { private final ElasticsearchQueryFactory queryFactory; public ElasticBookSearchRepositoryImpl(ElasticsearchQueryFactory queryFactory) { this.queryFactory = queryFactory; } public ElasticsearchQuery<ElasticsearchBook> findByQueryStringQuery(String queryString, Pageable pageable) { QElasticsearchBook elasticsearchBook = QElasticsearchBook.elasticsearchBook; StringPath bookName = elasticsearchBook.bookName; return queryFactory .selectFrom(elasticsearchBook) .where(bookName.contains(queryString)) .offset(pageable.getOffset()) .limit(pageable.getPageSize()); } }
Java
복사
아래는 JPQL로 직접 쿼리를 보낼 때의 각 검색 API이다.

1. 검색API Template

{ "size": "[페이징]몇개의 결과를 반환할지 결정한다(default: 10)", "from": "[페이징]어느 위치부터 반환할지 결정한다.(defalut: 0)", "timeout": "제한시간을 설정하여 제한시간까지 조회된 문서만 조회한다.(default: 무한대)", "_source": { // 특정필드만 결과로 반환받고 싶을때 정의한다}, "sort": { // 특정필드를 기준으로 정렬할지 정의한다}, "query": { /* * [전문검색] * 검색될 조건을 정의한다. * 분석기에 의해 분석. */}, "filter": { /* * [조건검색] * 검색 결과 중 특정한 값을 다시 보여준다 * 결과 내에서 재검색 때 사용하는 기능 중 하나다. * 다만 필터를 사용하게 되면 자동으로 score 값이 정렬되지 않는다. * (_score 정렬을 추가하면 가능하다.) */}, "aggs": { // 통계 또는 집계데이터 사용시 정의한다.} }
JSON
복사

2. 검색 파라메터

2.1 Multi Index검색

# 특정인덱스 정의 POST [인덱스1],[인덱스2]/_search # *(와일드카드) 사용 POST [인덱스명]*/_search
Shell
복사
문법
연산자
lt
<
gt
>
lte
<=
gte
>=
POST [인덱스]/_search { "query": { "range": { "필드명": { "gte": "2016",// >= 2016"lte": "2017"// <= 2017} } } }
JSON
복사

2.3 operator

AND조회
POST [인덱스]/_search { "query": { "match": { "필드명": { "query": "자전차왕 엄복동", "operator": "and"} } } } /* OR연산 결과 자전차왕 엄복동 자전차왕 홍길동 오토바이왕 엄복동 .... AND연산 결과 자전차왕 엄복동 자전차왕 엄복동 김복동 ... */
JSON
복사

2.4 minimum_should_match

매치 최소개수 지정

2.5 boost

특정필드에 가중치 부여하여 score을 높이고 상위에 노출하도록 함

3. 문자열 검색

match와 term의 차이

query
필드 타입
설명
match
text
쿼리를 수행하기전에 분석기를 통해 텍스트르 분석한 후 검색을 수행. text 데이터타입을 검색할때 match를 사용.
term
keyword
별도의 분석작업을 수행하지않고 입력된 텍스트가 존재하는 문서를 찾음. keyword 데이터타입을 검색할때 term를 사용.
query_string
-
엘라스틱서치에 내장된 쿼리분석기로 검색.

3.1 match

3.1.1 match_all

색인된 모든문서 조회
POST [인덱스]/_search { "query": { "match_all": {} } }
JSON
복사

3.1.2 match / multi_match

문장을 형태소 분석을 통해 텀으로 분리 후 텀으로 검색질의 수행.
검색어가 분석되야 할 경우 사용한다.
POST [인덱스]/_search { "query": { "match": { "[필드]": "[검색할 키워드]"} } } POST [인덱스]/_search { "query": { "multi_match": { "query": "[검색할 키워드]", "fields": ["[필드1]", "[필드2]"] } } }
JSON
복사

3.2 term

정확히 매칭되지않거나, 대소문자가 다른경우 조회되지 않음.
POST [인덱스]/_search { "query": { "term": { "[필드]": "[검색할 키워드]"} } }
JSON
복사

3.3 query_string

엘라스틱서치에 기본적으로 내장된 쿼리분석기로 검색
// 전체검색 POST [인덱스]/_search { "query": { "query_string": { "query": "[검색할 키워드]"} } } // 필드검색 POST [인덱스]/_search { "query": { "query_string": { "default_field": "[필드명]", "query": "[검색할 키워드]"} } }
JSON
복사

4. 조건검색

4.1 bool

AND, OR, IN 조건을 설정한다.
ElasticSearch
SQL
must: [필드]
AND [컬럼] = [조건]
must_not: [필드]
AND [컬럼] != [조건]
should: [필드]
OR [컬럼] = [조건]
filter: [필드]
[컬럼] IN ( [조건] )
조건 : 장르 = '코미디' AND 국가 = '한국' AND 타입 != '단편' POST [인덱스]/_search { "query": { "bool": { "must": [ { "term": { "장르": "코미디"} }, { "match": { "국가": "한국"} } ], "must_not": [ { "match": { "타입": "단편"} } ] } } }
JSON
복사

5. 그외..

5.1 Prefix Query

접두어가 있는 문서를 검색하고자 할때

5.2 Exists Query

실제 값이 존재하는 문서만 찾고싶을때.

5.3 Wildcard Query

와일드카드와 일치하는 구문을 찾는다.

5.4 Nested Query

부모자식 관계 형태(Object)의 데이터타입인 Nested타입 필드 검색할때 사용.

5.5 Multi Search API

여러건의 검색을 한번에 요청할때
POST _msearch {"index" : "[인덱스1]"} { "query" : { // 조건}, "from": 0, "size": 10} {"index" : "[인덱스2]"} { "query" : { // 조건}, "from": 0, "size": 10}
JSON
복사

5.6 Count API

문서 개수 조회
POST [인덱스]/_count { "query" : { // 조건} }
JSON
복사

5.7 Explain API (_score)

_score값이 어떻게 계산된것인지 확인하고싶을때 사용.

5.8 Profile API (튜닝/디버깅)

쿼리에 대한 상세한 수행계획과 수행계획별 수행된 시간 조회.