[Springboot] ElasticSearch로 검색 api 만들기

나르·2022년 5월 27일
0

Spring

목록 보기
17/25
post-thumbnail

Elasticsearch 설치

Elasticsearch 실행을 위해서는 자바1.8 이상의 버전이 설치되어 있어야 합니다.
각 버전별로 필요한 자바 버전은 지원 매트릭스 페이지에서 확인이 가능합니다.

Download Elasticsearch
Mac에서는 brew로 설치가 가능합니다.

brew install elasticsearch

dependency

Spring Data Elasticsearch

implementation 'org.springframework.data:spring-data-elasticsearch:4.4.2'

config

@EnableElasticsearchRepositories(basePackages = "dev.demo.searchmodule.repository.search")
@Configuration
public class ElasticsearchConfig {
    @Value("${elasticsearch.host}")
    private String host;

    @Value("${elasticsearch.port}")
    private String port;

    @Bean(destroyMethod = "close")
    public RestHighLevelClient elasticsearchClient() {
        ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo(host + ":" + port)
                .withConnectTimeout(10000)
                .withSocketTimeout(10000)
                .build();

        return RestClients.create(clientConfiguration).rest();
    }
}

Spring Elasticsearch Client
spring-data-elasticsearch 4.0.0 이상부터는TransportClient 클래스가 Deprecated 되어 RestHighLevelClient 또는 ReactiveRestLevelClients 만 사용이 가능합니다.

JPA와 함께 사용한다면 @EnableJpaRepositories@EnableElasticsearchRepositories가 모두 스캔하려하기 때문에 basePackage를 명시해주고, @EnableJpaRepositories 에서는 해당 패키지를 제외해주는 것이 좋습니다.

@EnableJpaRepositories(excludeFilters = @ComponentScan.Filter(
    type = FilterType.ASSIGNABLE_TYPE,
    classes = BoardSearchRepository.class))
@SpringBootApplication
public class ElasticsearchApplication {
    public static void main(String[] args) {
        SpringApplication.run(ElasticsearchApplication.class, args);
    }
}

더 많은 정보는 공식문서 Elasticsearch Client에 나와있습니다.

Document

@Getter
@Document(indexName = "gamewood-board")
public class BoardSearch {

    @Id
    private ObjectId id;

    @Field("board_id")
    private final Long boardId;
    @Field("member_no")
    private final String memberNo;

    private final String author;
    private final String title;
    private final String content;

    @Builder
    @PersistenceConstructor
    public BoardSearch(Long boardId, String title, String content, String author) {
        this.boardId = boardId;
        this.title = title;
        this.content = content;
        this.author = author;
    }
}

@PersistenceConstructor가 부착된 생성자를 통해 ES에 저장된 Document가 Aggregate로 재구성됩니다.

repository

@Repository
public interface BoardSearchRepository extends ElasticsearchRepository<BoardSearch, String> {

    List<BoardSearch> findByAuthor(String author);
}

Spring Data JPA처럼 메서드 이름을 기반으로 CRUD 명령 쿼리를 생성할 수 있고, 복잡한 쿼리를 질의해야한다면 아래와 같이 Operations를 사용하여 쿼리를 작성할 수 있습니다.

@RequiredArgsConstructor
@Repository
public class BoardSearchRepository {

    private final ElasticsearchOperations elasticsearchOperations;

    public List<BoardSearch> searchBoard(String keyword, List<String> categories, Pageable pageable) {
        Query query = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.boolQuery()
                        .must(QueryBuilders.queryStringQuery(keyword)
                                .field(TITLE.value).field(CONTENT.value).field(AUTHOR.value))
                ).withPageable(pageable).build();
        SearchHits<BoardSearch> searchHits = elasticsearchOperations.search(query, BoardSearch.class);
        
        return searchHits.stream()
                .map(SearchHit::getContent)
                .collect(Collectors.toList());
    }

    @RequiredArgsConstructor
    enum Field {
        TITLE("title"),
        CONTENT("content"),
        AUTHOR("author"),
        CATEGORY("category");

        private final String value;
    }
}

Querybuilder

Elasticsearch Query

쿼리는 크게 CriteriaQuery, StringQuery, NativeSearchQuery 3가지 방식으로 구현이 가능합니다.

CriteriaQuery

Criteria criteria = new Criteria("price").is(42.0);
Query query = new CriteriaQuery(criteria);

StringQuery

StringQuery는 JSON String 형태로 쿼리를 받습니다.

Query query = new SearchQuery("{ \"match\": { \"firstname\": { \"query\": \"Jack\" } } } ");

NativeSearchQuery

NativeSearchQuery는 Aggregate를 사용하거나 복잡한 쿼리를 생성하는데 효과적인 Query 구현체입니다.

Query query = new NativeSearchQueryBuilder()
    .addAggregation(terms("lastnames").field("lastname").size(10)) //
    .withQuery(QueryBuilders.matchQuery("firstname", firstName))
    .build();

Ref.

spring-data-elasticsearch 공식 문서
ES 가이드북
[spring] 스프링 elasticsearch NativeSearchQuery 사용방법
Spring Data Elasticsearch 설정 및 검색 기능 구현

profile
💻 + ☕ = </>

0개의 댓글