Въведение в Spring Data Elasticsearch

1. Общ преглед

В този урок ще изследваме основите на Spring Data Elasticsearch по кодиран и практичен начин.

Ще покажем как да индексираме, търсим и заявяваме Elasticsearch в приложение Spring чрез Spring Data Elasticsearch. Spring Data Elasticseach е Spring модул, който реализира Spring Data, като по този начин предлага начин за взаимодействие с популярната търсачка, базирана на Lucene с отворен код.

Докато Elasticsearch може да работи без трудно дефинирана схема, често срещана практика е да се проектира такава и да се създадат съпоставяния, указващи вида на данните, които се очакват в определени полета . Когато документът се индексира, полетата му се обработват според техните типове. Например текстовото поле ще бъде токенизирано и филтрирано в съответствие с правилата за картографиране. Бихме могли да създадем и собствени филтри и токенизатори.

За по-голяма простота ще използваме изображение на докер за нашия екземпляр Elasticsearch, въпреки че всеки екземпляр на Elasticsearch, който слуша на порт 9200, ще го направи .

Започваме с изстрелване на нашия екземпляр Elasticsearch:

docker run -d --name es762 -p 9200:9200 -e "discovery.type=single-node" elasticsearch:7.6.2

2. Пролетни данни

Spring Data помага да се избегне шаблонния код. Например, ако дефинираме интерфейс на хранилище, който разширява интерфейса ElasticsearchRepository, предоставен от Spring Data Elasticsearch , CRUD операциите за съответния клас документ ще бъдат предоставени по подразбиране.

Освен това, просто чрез деклариране на методи с имена в предварително дефиниран формат, за нас се генерират имплементации на методи - няма нужда да се пише реализация на интерфейса на хранилището.

Ръководствата на Baeldung за Spring Data предоставят най-важното, за да започнете по темата.

2.1. Зависимост на Maven

Spring Data Elasticsearch предоставя Java API за търсачката. За да го използваме, трябва да добавим нова зависимост към pom.xml :

 org.springframework.data spring-data-elasticsearch 4.0.0.RELEASE 

2.2. Дефиниране на интерфейси на хранилището

За да дефинираме нови хранилища, ние разширяваме един от предоставените интерфейси на хранилището, замествайки родовите типове с нашите действителни типове документи и първични ключове.

Важно е да се отбележи, че ElasticsearchRepository се простира от PagingAndSortingRepository. Това позволява вградена поддръжка за разбиване на страници и сортиране.

В нашия пример ще използваме функцията за пейджинг в нашите методи за персонализирано търсене:

public interface ArticleRepository extends ElasticsearchRepository { Page findByAuthorsName(String name, Pageable pageable); @Query("{\"bool\": {\"must\": [{\"match\": {\"authors.name\": \"?0\"}}]}}") Page findByAuthorsNameUsingCustomQuery(String name, Pageable pageable); }

С метода findByAuthorsName проксито на хранилището ще създаде реализация въз основа на името на метода. Алгоритъмът за разделителна способност ще определи, че трябва да осъществи достъп до свойството на авторите и след това да търси свойството за име на всеки елемент.

Вторият метод, findByAuthorsNameUsingCustomQuery , използва персонализирана логическа заявка на Elasticsearch, дефинирана с помощта на анотацията @Query , която изисква стриктно съвпадение между името на автора и предоставения аргумент за име .

2.3. Конфигурация на Java

Когато конфигурираме Elasticsearch в нашето Java приложение, трябва да дефинираме как да се свържем с екземпляра Elasticsearch. За това използваме RestHighLevelClient, който се предлага от зависимостта Elasticsearch:

@Configuration @EnableElasticsearchRepositories(basePackages = "com.baeldung.spring.data.es.repository") @ComponentScan(basePackages = { "com.baeldung.spring.data.es.service" }) public class Config { @Bean public RestHighLevelClient client() { ClientConfiguration clientConfiguration = ClientConfiguration.builder() .connectedTo("localhost:9200") .build(); return RestClients.create(clientConfiguration).rest(); } @Bean public ElasticsearchOperations elasticsearchTemplate() { return new ElasticsearchRestTemplate(client()); } }

Използваме стандартна анотация за стил на пролетта. @EnableElasticsearchRepositories ще накара Spring Data Elasticsearch да сканира предоставения пакет за хранилища Spring Data.

За да комуникираме с нашия Elasticsearch сървър, ние използваме прост RestHighLevelClient . Докато Elasticsearch предоставя множество типове клиенти, използването на RestHighLevelClient е добър начин за бъдеща комуникация със сървъра.

И накрая, ние създадохме ElasticsearchOperations боб за изпълнение на операции на нашия сървър. В този случай създаваме екземпляр на ElasticsearchRestTemplate .

3. Картографиране

Съпоставянията се използват за дефиниране на схема за нашите документи. Като дефинираме схема към нашите документи, ние ги защитаваме от нежелани резултати, като например картографиране към тип, който не бихме искали.

Нашият обект е прост документ, наречен Article, където id е от типа String . Също така уточняваме, че такива документи трябва да се съхраняват в индекс с име на блог в рамките на типа статия .

@Document(indexName = "blog", type = "article") public class Article { @Id private String id; private String title; @Field(type = FieldType.Nested, includeInParent = true) private List authors; // standard getters and setters }

Индексите могат да имат няколко вида. Можем да използваме тази функция за реализиране на йерархии.

Полето за авторите е маркирано като FieldType.Nested . Това ни позволява да дефинираме отделно класа Автор , но имаме отделните екземпляри на автора да бъдат вградени в документ Article, когато той е индексиран в Elasticsearch.

4. Индексиране на документи

Spring Data Elasticsearch обикновено автоматично създава индекси въз основа на обектите в проекта. Можем обаче да създадем индекс и програмно чрез клиентския шаблон:

elasticsearchTemplate.indexOps(Article.class).create();

След това можем да добавим документи към индекса:

Article article = new Article("Spring Data Elasticsearch"); article.setAuthors(asList(new Author("John Smith"), new Author("John Doe"))); articleRepository.save(article);

5. Запитване

5.1. Заявка, базирана на име на метод

Когато използваме заявка, базирана на име на метод, ние пишем методи, които определят заявката, която искаме да изпълним. По време на настройката Spring Data ще анализира подписа на метода и ще създаде съответно заявките:

String nameToFind = "John Smith"; Page articleByAuthorName = articleRepository.findByAuthorsName(nameToFind, PageRequest.of(0, 10));

Чрез извикване на findByAuthorsName с обект PageRequest получаваме първата страница с резултати (номерирането на страниците е нулево), като тази страница съдържа най-много 10 статии. Обектът на страницата също така предоставя общия брой посещения за заявката заедно с друга удобна информация за разбиране на страницата.

5.2. Персонализирана заявка

There are a couple of ways to define custom queries for Spring Data Elasticsearch repositories. One way is to use the @Query annotation, as demonstrated in section 2.2.

Another option is to use the query builder to create our custom query.

Having to search for articles that have the word “data” in the title, we could just create a NativeSearchQueryBuilder with a Filter on the title:

Query searchQuery = new NativeSearchQueryBuilder() .withFilter(regexpQuery("title", ".*data.*")) .build(); SearchHits articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog");

6. Updating and Deleting

In order to update a document, we first must retrieve it:

String articleTitle = "Spring Data Elasticsearch"; Query searchQuery = new NativeSearchQueryBuilder() .withQuery(matchQuery("title", articleTitle).minimumShouldMatch("75%")) .build(); SearchHits articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"); Article article = articles.getSearchHit(0).getContent();

Then, we can make changes to the document just by editing the content of the object using its assessors:

article.setTitle("Getting started with Search Engines"); articleRepository.save(article);

As for deleting, there are several options. We can retrieve the document and delete it using the delete method:

articleRepository.delete(article);

Можем да го изтрием и по id, когато е известно:

articleRepository.deleteById("article_id");

Също така е възможно да създадете персонализирани изтривания чрез заявки и да използвате функцията за групово изтриване, предлагана от Elasticsearch:

articleRepository.deleteByTitle("title");

7. Заключение

В този урок разгледахме как да се свържем и да използваме Spring Data Elasticsearch. Обсъдихме как можем да правим заявки, да актуализираме и изтриваме документи. Освен това обсъдихме и как да създаваме персонализирани заявки и те не отговарят на това, което се предлага от Spring Data Elasticsearch.

Както обикновено, изходният код, използван в този урок, може да бъде намерен в GitHub.