Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Next Level Elasticsearch Integration with Sprin...
Search
Peter-Josef Meisch
October 15, 2020
Programming
1
130
Next Level Elasticsearch Integration with Spring Data Elasticsearch
The slides for my session at ElasticON Global on October 14th and 15th 2020
Peter-Josef Meisch
October 15, 2020
Tweet
Share
Other Decks in Programming
See All in Programming
CSS Linter の現在地 2025年のベストプラクティスを探る
ryo_manba
10
3.2k
大規模アプリのDIフレームワーク刷新戦略 ~過去最大規模の並行開発を止めずにアプリ全体に導入するまで~
mot_techtalk
0
250
CSC509 Lecture 01
javiergs
PRO
1
430
あなたの知らない「動画広告」の世界 - iOSDC Japan 2025
ukitaka
0
310
育てるアーキテクチャ:戦い抜くPythonマイクロサービスの設計と進化戦略
fujidomoe
1
150
CI_CD「健康診断」のススメ。現場でのボトルネック特定から、健康診断を通じた組織的な改善手法
teamlab
PRO
0
150
詳しくない分野でのVibe Codingで困ったことと学び/vibe-coding-in-unfamiliar-area
shibayu36
1
1k
CSC305 Lecture 03
javiergs
PRO
0
230
パフォーマンスチューニングで Web 技術を深掘り直す
progfay
18
4.8k
議事録の要点整理を自動化! サーバレス Bot 構築術
penpeen
3
1.6k
ててべんす独演会〜Flowの全てを語ります〜
tbsten
1
220
非同期jobをtransaction内で 呼ぶなよ!絶対に呼ぶなよ!
alstrocrack
0
350
Featured
See All Featured
Navigating Team Friction
lara
189
15k
BBQ
matthewcrist
89
9.8k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
33
2.4k
Why You Should Never Use an ORM
jnunemaker
PRO
59
9.5k
Practical Orchestrator
shlominoach
190
11k
Agile that works and the tools we love
rasmusluckow
330
21k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
140
34k
[RailsConf 2023] Rails as a piece of cake
palkan
57
5.9k
Building Adaptive Systems
keathley
43
2.8k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
46
7.6k
Typedesign – Prime Four
hannesfritz
42
2.8k
Transcript
1 ElasticON Global Peter-Josef Meisch Spring Data Elasticsearch Project Lead
2 Nothing will stop you being creative more effectively as
the fear of making a mistake. John Cleese
3 Next Level Elasticsearch Integration with Spring Data Elasticsearch
What is Spring Data Elasticsearch?
“Spring Data’s mission is to provide a familiar and consistent,
Spring-based programming model for data access while still retaining the special traits of the underlying data store.”
Configure the connection to Elasticsearch
Configure the connection to Elasticsearch @Configuration public class RestClientConfig extends
AbstractElasticsearchConfiguration { @Override @Bean public RestHighLevelClient elasticsearchClient() { ClientConfiguration clientConfiguration = ClientConfiguration.builder() .connectedTo("localhost:9200") .build(); return RestClients.create(clientConfiguration).rest(); } }
Configure the connection to Elasticsearch @Configuration public class RestClientConfig extends
AbstractElasticsearchConfiguration { @Override @Bean public RestHighLevelClient elasticsearchClient() { ClientConfiguration clientConfiguration = ClientConfiguration.builder() .connectedTo("localhost:9200") .withProxy("localhost:8080") .build(); return RestClients.create(clientConfiguration).rest(); } }
Configure the connection to Elasticsearch @Configuration public class RestClientConfig extends
AbstractElasticsearchConfiguration { @Override @Bean public RestHighLevelClient elasticsearchClient() { ClientConfiguration clientConfiguration = ClientConfiguration.builder() .connectedTo("localhost:9200") .usingSsl() .build(); return RestClients.create(clientConfiguration).rest(); } }
Configure the connection to Elasticsearch @Configuration public class RestClientConfig extends
AbstractElasticsearchConfiguration { @Override @Bean public RestHighLevelClient elasticsearchClient() { ClientConfiguration clientConfiguration = ClientConfiguration.builder() .connectedTo("localhost:9200") .withBasicAuth("myuser", "mypassword") .build(); return RestClients.create(clientConfiguration).rest(); } }
Configure the connection to Elasticsearch @Configuration public class RestClientConfig extends
AbstractElasticsearchConfiguration { @Override @Bean public RestHighLevelClient elasticsearchClient() { ClientConfiguration clientConfiguration = ClientConfiguration.builder() .connectedTo("localhost:9200") .withPathPrefix("customer1") .build(); return RestClients.create(clientConfiguration).rest(); } }
Configure the connection to Elasticsearch Supplier<HttpHeaders> currentTimeHeaders = () ->
{ HttpHeaders headers = new HttpHeaders(); headers.add("currentTime", LocalDateTime.now() .format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); return headers; }; ClientConfiguration clientConfiguration = ClientConfiguration.builder() .connectedTo("localhost:9200") .withHeaders(currentTimeHeaders) .build();
Entity definition
Entity definition public class Person { @Id private String id;
private String lastName; private String firstName; private LocalDate birthDate; }
Entity definition @Document(indexName = "person") public class Person { @Id
private String id; private String lastName; private String firstName; private LocalDate birthDate; }
Entity definition @Document(indexName = "person") public class Person { @Id
private String id; @Field(type = FieldType.Text) private String lastName; @Field(type = FieldType.Text) private String firstName; private LocalDate birthDate; }
Entity definition @Document(indexName = "person") public class Person { @Id
private String id; @Field(type = FieldType.Text) private String lastName; @Field(type = FieldType.Text) private String firstName; @Field(type = FieldType.Date, format = DateFormat.basic_date) private LocalDate birthDate; }
ElasticsearchOperations
IndexOperations • index creation and deletion • index settings •
index mappings • index templates • alias management • refresh operation
IndexOperations private ElasticsearchOperations operations ; // injected by Spring IndexOperations
indexOps = operations.indexOps(Person.class); indexOps.create(); indexOps.putMapping(); PutTemplateRequest putTemplateRequest = PutTemplateRequest.builder("template-name", "log-*") .withSettings(settings) .withMappings(mapping) .withAliasActions(aliasActions) .build(); indexOps.putTemplate(putTemplateRequest);
IndexOperations private ElasticsearchOperations operations; // injected by Spring IndexOperations indexOps
= operations.indexOps(Person.class) ; indexOps.create(); indexOps.putMapping(); PutTemplateRequest putTemplateRequest = PutTemplateRequest.builder("template-name", "log-*") .withSettings(settings) .withMappings(mapping) .withAliasActions(aliasActions) .build(); indexOps.putTemplate(putTemplateRequest);
IndexOperations private ElasticsearchOperations operations; // injected by Spring IndexOperations indexOps
= operations.indexOps(Person.class); indexOps.create(); indexOps.putMapping(); PutTemplateRequest putTemplateRequest = PutTemplateRequest.builder("template-name", "log-*") .withSettings(settings) .withMappings(mapping) .withAliasActions(aliasActions) .build(); indexOps.putTemplate(putTemplateRequest);
IndexOperations private ElasticsearchOperations operations; // injected by Spring IndexOperations indexOps
= operations.indexOps(Person.class); indexOps.create(); indexOps.putMapping(); PutTemplateRequest putTemplateRequest = PutTemplateRequest.builder("template-name", "log-*") .withSettings(settings) .withMappings(mapping) .withAliasActions(aliasActions) .build(); indexOps.putTemplate(putTemplateRequest) ;
DocumentOperations • save • get • delete • exists •
update
SearchOperations • count • search Query based operations
NativeSearchQuery import static org.elasticsearch.index.query.QueryBuilders.*; import static org.elasticsearch.search.aggregations.AggregationBuilders.*; Query query =
new NativeSearchQueryBuilder() .addAggregation( terms("lastNames").field("lastName").size(10) ) .withQuery( matchQuery("firstName", firstName) ) .build(); SearchHits<Person> searchHits = operations.search(query, Person.class);
StringQuery Query query = new StringQuery( "{" + " \"bool\":
{" + " \"must\": [" + " {" + " \"match\": {" + " \"lastName\": \"Smith\"" + " }" + " }" + " ]" + " }" + "}"); SearchHits<Person> searchHits = operations.search(query, Person.class);
CriteriaQuery Criteria criteria = new Criteria("lastName").is("Smith") .and("firstName").is("James"); Query query =
new CriteriaQuery(criteria); SearchHits<Person> searchHits = operations.search(query, Person.class);
Return types
SearchHit<T • id • index name • the entity of
type T • score • sort values • highlight fields • inner hits
SearchHits<T • number of total hits • total hits relation
(eq, gte) • list of SearchHit<T> objects • max score • aggregations
ElasticsearchRepository
Repository interface PersonRepository extends ElasticsearchRepository< Person, String > { }
// ElasticsearchRepository // +PagingAndSortingRepository // + CrudRepository // + Repository
Repository count() delete(T) deleteAll() deleteAll(Iterable<? extends T) deleteById(ID) existsById(ID) findAll()
findAll(Pageable) findAll(Sort) findAllById(Iterable<ID>) findById(ID) save(T) saveAll(Iterable<T>) searchSimilar(T entity, String[] fields, Pageable pageable)
Repository methods interface PersonRepository extends ElasticsearchRepository< Person, String > {
List<Person> searchByFirstName(String name); List<Person> findByFirstNameOrderByLastNameAsc(String name); List<Person> queryByBirthDateBefore(LocalDate date); }
Repository methods interface PersonRepository extends ElasticsearchRepository<Person, String> { @Query(value =
"{\"fuzzy\":{\"lastName\":\"?0\"}}") List<Person> findByLastNameFuzzy(String lastName); }
Repository method return types interface PersonRepository extends ElasticsearchRepository<Person, String> {
List<Person> searchByFirstName(String name); }
Repository method return types interface PersonRepository extends ElasticsearchRepository<Person, String> {
Stream<Person> searchByFirstName(String name); }
Repository method return types interface PersonRepository extends ElasticsearchRepository<Person, String> {
List<SearchHit<Person>> searchByFirstName(String name); }
Repository method return types interface PersonRepository extends ElasticsearchRepository<Person, String> {
Stream<SearchHit<Person>> searchByFirstName(String name); }
Repository method return types interface PersonRepository extends ElasticsearchRepository<Person, String> {
SearchHits<Person> searchByFirstName(String name); }
Repository method return types interface PersonRepository extends ElasticsearchRepository<Person, String> {
SearchPage<Person> searchByFirstName(String name, Pageable page); }
Repository usage @RestController @RequestMapping(”/persons”) public class PersonController { private PersonRepository
repository; public PersonController(PersonRepository repository) { this.repository = repository; } @GetMapping(”/firstName/{name}”) List<Person> byFirstName( @PathVariable(”name”) String name) { return repository.searchByFirstName(name) ; } }
Repository method with highlight definition interface PersonRepository extends ElasticsearchRepository<Person, String>
{ @Highlight(fields = { @HighlightField(name = "firstName") }) SearchHits<Person> searchByFirstName(String name); } repository.searchByFirstName(”James”) .forEach(searchHit -> { List<String> highlights = searchHit.getHighlightField("firstName"); // ... });
What else?
Lifecycle events @Component public class PersonBeforeConvertCallback implements BeforeConvertCallback<Person> { @Override
public Person onBeforeConvert(Person person, IndexCoordinates indexCoordinates) { if (person.getId() == null) { person.setId(UUID.randomUUID().toString()); } return person; } }
Auditable Entity @Document(indexName = "person") public class Person implements Persistable<String>
{ @Id private String id; @CreatedDate @Field(type = FieldType.Date, format = DateFormat.basic_date_time) private Instant created; @CreatedBy private String createdBy; @Override public boolean isNew() { return id == null || (createdBy == null && created == null); } }
We need contributors! Spring Data Elasticsearch is a community-driven project
49 Thank You! https://spring.io/projects/spring-data-elasticsearch https://github.com/spring-projects/spring-data-elasticsearch @sothawo
[email protected]