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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
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
Oxlintはいいぞ
yug1224
5
1.4k
【卒業研究】会話ログ分析によるユーザーごとの関心に応じた話題提案手法
momok47
0
200
Package Management Learnings from Homebrew
mikemcquaid
0
230
24時間止められないシステムを守る-医療ITにおけるランサムウェア対策の実際
koukimiura
1
110
dchart: charts from deck markup
ajstarks
3
1k
AIエージェントのキホンから学ぶ「エージェンティックコーディング」実践入門
masahiro_nishimi
5
500
CSC307 Lecture 09
javiergs
PRO
1
840
副作用をどこに置くか問題:オブジェクト指向で整理する設計判断ツリー
koxya
1
610
今から始めるClaude Code超入門
448jp
8
9k
インターン生でもAuth0で認証基盤刷新が出来るのか
taku271
0
190
高速開発のためのコード整理術
sutetotanuki
1
410
コントリビューターによるDenoのすゝめ / Deno Recommendations by a Contributor
petamoriken
0
210
Featured
See All Featured
Docker and Python
trallard
47
3.7k
A Tale of Four Properties
chriscoyier
162
24k
Imperfection Machines: The Place of Print at Facebook
scottboms
269
14k
Typedesign – Prime Four
hannesfritz
42
2.9k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
76
The Power of CSS Pseudo Elements
geoffreycrofte
80
6.2k
[RailsConf 2023] Rails as a piece of cake
palkan
59
6.3k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.3k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
60
42k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
196
71k
AI: The stuff that nobody shows you
jnunemaker
PRO
2
270
SEO for Brand Visibility & Recognition
aleyda
0
4.2k
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]