본문 바로가기

elasticsearch

sping data elasticsearch 정리 ( spring 에서 es 사용 관련)

반응형

여전히 공식 문서 ( http://projects.spring.io/spring-data-elasticsearch/ ) 를 참고하는게 가장 좋으며,

기록하면서 보면 기억에 남을까 하여 정리


3.2 쿼리 메소드

1. Repository 를 상속받은 Interface 를 구현하거나 subinterface 를 사용 ( interface를 구현하는게 아니라 별도 interface 를 만듦)

2. 쿼리 메소드를 선언 ( findAll 등 interface 에 선언 되어 있는 것들)

3. JavaConfig나 XML 설정을 통해서 proxy instance 를 설정 ( 이 부분은 추후 자세히 설명이 되어 있는듯 하지만 아래와 같이 설정 함

@EnableJpaRepositories // @Enable${store}Repositories 형태로 사용됨

class Config {}


OR


<jpa:repositories base-package="com.acme.repositories" />

4. 생성한 interface 를 사용하고자 하는 부분에서 사용


3.3.2 multiple spring data module 를 사용하는 repositories

어노테이션이 붙은 도메인을 사용할 수 있음 ( JPA 의 @Entity 나 spring data 의 mongodb/es 같은 @Document)

중복적으로 어노테이션을 사용할 수 있음

@Entiry

@Document

public class Persion { ... }


3.4 쿼리 메소드 정의

메소드의 이름 에 따라 쿼리가 생성된다. ( find...By, read...By, count..... By, And, Or 등 )
public interface PersonRepository extends Repository<User, Long> {
List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);
// Enables the distinct flag for the query
List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);
List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname);
// Enabling ignoring case for an individual property
List<Person> findByLastnameIgnoreCase(String lastname);
// Enabling ignoring case for all suitable properties
List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname);
// Enabling static ORDER BY for a query
List<Person> findByLastnameOrderByFirstnameAsc(String lastname);
List<Person> findByLastnameOrderByFirstnameDesc(String lastname);
}

추가적으로 Between, LessThan, GreaterThan, LIke 등도 가능하다.

검색 인자로 클래스를 줄 경우 클래스 인지 별도 속성인지 구분이 안 가기 때문에 클래스 (traversal ) 일 경우 앞에 언더바 ( _ ) 를 붙임


3.4.4 특수 파라미터

Pageable, Sort 등을 인자로 줌으로써 다이나믹하게ㅔ 쿼리 메소드를 생성 할 수 있다. ( 참고로 page 0이 첫페이지임)

Page<Person> or Slice<Person> findByLastname(String lastname, Pageable pageable);
List<Person> findByLastname(String lastname, Sort sort);


3.4.5 Limiting 쿼리

first, top + size 조합으로 결과를 제한할 수 있다.
(queryFirst10ByLastname(String lastname, Pageable pageable);
findTopByLastname 처럼 )

3.4.7 비동기 쿼리

스프링의 비동기 실행 방식을 이용하여 할 수 있음

@Async 어노테이션과 Future 클래스 활용 가능


4. Elasticsearch Repositories

Transport Client 나 Node Client 엘리먼트를 이용하여 엘라스틱 서버(인스턴스)를 사용한다.

<elasticsearch:transport-client id="client" cluster-nodes="localhost:9300,someip:9300" />
<elasticsearch:node-client id="client" local="true" />

위 XML 설정 외에도 어노테이션/JavaConfig 를 이용하여 설정할 수도 있다.

아래 설정은 ElasticsearchTemplate 를 이용해서 Embedded Elasticsearch Server 를 설정하는 것으로 @EnableElasticsearchRepositories 어노테이션을 사용해야 함

@Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchTemplate(NodeBuilder.nodeBuilder().local(true).node().client());
}

4.2. 쿼리 메소드

다양한 메소드들이 있고 해당 메소드와 ES 쿼리를 샘플로 매칭한 부분은 위에 언급한 공식 가이드 문서에 있으니 참고 (PDF 로 42 페이지쯤? )

4.2.3 @Query 어노테이션 사용

메소드에 @Query 어노테이션을 사용 할 수 있음 (ES 쿼리를 잘 알아야 함 )
?0, ?1 로 메소드 인자와 바인딩 가능함
public interface BookRepository extends ElasticsearchRepository<Book, String> {
@Query("{"bool" : {"must" : {"field" : {"name" : " ? 0"}}}}")
Page<Book> findByName(String name, Pageable pageable);
}

5.1 필터 빌더

쿼리 속도 향상
private ElasticsearchTemplate elasticsearchTemplate;
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQuery())
.withFilter(boolFilter().must(termFilter("id", documentId)))
.build();
Page<SampleEntity> sampleEntities =
elasticsearchTemplate.queryForPage(searchQuery,SampleEntity.class);

5.2. 사이즈가 큰 결과를 위해 Scan 과 Scroll 사용

ElasticsearchTemplate 에서 있는 scan 과 scroll 메소드를 사용
    SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQuery())
.withIndices("test-index")
.withTypes("test-type")
.withPageable(new PageRequest(0, 1))
.build();
String scrollId = elasticsearchTemplate.scan(searchQuery, 1000, false);
List<SampleEntity> sampleEntities = new ArrayList<SampleEntity>();
boolean hasRecords = true;
while (hasRecords) {
Page<SampleEntity> page = elasticsearchTemplate.scroll(scrollId, 5000L, new
ResultsMapper<SampleEntity>() {
@Override
public Page<SampleEntity> mapResults(SearchResponse response) {
List<SampleEntity> chunk = new ArrayList<SampleEntity>();
for (SearchHit searchHit : response.getHits()) {
if (response.getHits().getHits().length <= 0) {
return null;
}
SampleEntity user = new SampleEntity();
user.setId(searchHit.getId());
user.setMessage((String) searchHit.getSource().get("message"));
chunk.add(user);
}
return new PageImpl<SampleEntity>(chunk);
}
});
if (page != null) {
sampleEntities.addAll(page.getContent());
hasRecords = page.hasNextPage();
} else {
hasRecords = false;
}
}
}


반응형