Introdução ao Spring Data Elasticsearch

Introdução ao Spring Data Elasticsearch

1. Visão geral

Neste artigowe’ll explore the basics of Spring Data Elasticsearch de maneira prática e focada em código.

Mostraremos como indexar, pesquisar e consultar o Elasticsearch em um aplicativo Spring usando Spring Data - um módulo Spring para interação com um popular mecanismo de busca baseado em Lucene de código aberto.

Embora o Elasticsearch seja sem esquema, ele pode usar mapeamentos para informar o tipo de um campo. Quando um documento é indexado, seus campos são processados ​​de acordo com seus tipos. Por exemplo, um campo de texto será tokenizado e filtrado de acordo com as regras de mapeamento. Você também pode criar seus próprios filtros e tokenizadores.

2. Dados da Primavera

O Spring Data ajuda a evitar o código padrão. Por exemplo, se definirmos uma interface de repositório que estenda a interfaceElasticsearchRepository fornecida por Spring Data Elasticsearch,, as operações CRUD para a classe de documento correspondente serão disponibilizadas por padrão.

Além disso, simplesmente declarando métodos com nomes em um formato prescrito, as implementações de métodos são geradas para você - não há necessidade de escrever uma implementação da interface do repositório.

Você pode ler mais sobre Spring Datahere.

2.1. Dependência do Maven

O Spring Data Elasticsearch fornece uma API Java para o mecanismo de pesquisa. Para usá-lo, precisamos adicionar uma nova dependência aopom.xml:


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

2.2. Definindo Interfaces de Repositório

Em seguida, precisamos estender uma das interfaces de repositório fornecidas, substituindo os tipos genéricos pelos nossos documentos reais e tipos de chave primária.

Observe queElasticsearchRepository estendePagingAndSortingRepository, que fornece suporte integrado para paginação e classificação.

Em nosso exemplo, usaremos o recurso de paginação em nosso método de pesquisa personalizado:

public interface ArticleRepository extends ElasticsearchRepository {

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

Observe que adicionamos dois métodos personalizados. Com o métodofindByAuthorsName, o proxy do repositório criará uma implementação com base no nome do método. O algoritmo de resolução determinará que ele precisa acessar a propriedadeauthors e então pesquisar a propriedadename de cada item.

O segundo método,findByAuthorsNameUsingCustomQuery, usa uma consulta booleana Elasticsearch, definida usando a anotação@Query, que requer correspondência estrita entre o nome do autor e o argumentoname fornecido.

2.3. Configuração Java

Vamos agora explorar a configuração Spring de nossa camada de persistência aqui:

@Configuration
@EnableElasticsearchRepositories(basePackages = "com.example.spring.data.es.repository")
@ComponentScan(basePackages = { "com.example.spring.data.es.service" })
public class Config {

    @Value("${elasticsearch.home:/usr/local/Cellar/elasticsearch/5.6.0}")
    private String elasticsearchHome;

    @Value("${elasticsearch.cluster.name:elasticsearch}")
    private String clusterName;

    @Bean
    public Client client() {
        Settings elasticsearchSettings = Settings.builder()
          .put("client.transport.sniff", true)
          .put("path.home", elasticsearchHome)
          .put("cluster.name", clusterName).build();
        TransportClient client = new PreBuiltTransportClient(elasticsearchSettings);
        client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
        return client;
    }

    @Bean
    public ElasticsearchOperations elasticsearchTemplate() {
        return new ElasticsearchTemplate(client());
    }
}

Observe que estamos usando uma anotação padrão no estilo de ativação do Spring -@EnableElasticsearchRepositories - para verificar o pacote fornecido em busca de repositórios Spring Data.

Também estamos definindo umTransport Client simples:

  1. Ativamos o recurso sniffing para nosso cliente usando "client.transport.sniff"

  2. Também fornecemos o diretório de instalação do Elasticsearch usando "path.home"

  3. Se o nome do cluster não for "elasticsearch", precisamos fornecê-lo usando "cluster.name"

Finalmente - também estamos configurando um beanElasticsearchOperations -elasticsearchTemplate - como nosso cliente para trabalhar com o servidor Elasticsearch.

3. Mapeamentos

Vamos agora definir nossa primeira entidade - um documento chamadoArticle com uma Stringid:

@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
}

Observe que na anotação@Document, indicamos que as instâncias desta classe devem ser armazenadas no Elasticsearch em um índice denominado “blog“, e com um tipo de documento de “article“. Documentos com muitostypes diferentes podem ser armazenados no mesmoindex.

Observe também que o campoauthors está marcado comoFieldType.Nested. Isso nos permite definir a classeAuthor separadamente, mas ter as instâncias individuais do autor embutidas em um documentoArticle quando ele é indexado no Elasticsearch.

4. Documentos de indexação

O Spring Data Elasticsearch geralmente cria automaticamente índices com base nas entidades no projeto.

No entanto, você também pode criar um índice programaticamente, através do modelo do cliente:

elasticsearchTemplate.createIndex(Article.class);

Depois que o índice estiver disponível, podemos adicionar um documento ao índice.

Vamos dar uma rápida olhada em um exemplo - indexando um artigo com dois autores:

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

5. Consulta

5.1. Consulta baseada no nome do método

A classe de repositório que definimos anteriormente tinha um métodofindByAuthorsName - que podemos usar para encontrar artigos pelo nome do autor:

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

ChamandofindByAuthorName com um objetoPageRequest, obtemos a primeira página de resultados (a numeração da página é baseada em zero), com essa página contendo no máximo 10 artigos.

5.2. Uma Consulta Personalizada

Existem algumas maneiras de definir consultas personalizadas para os repositórios do Spring Data Elasticsearch. Uma maneira é usar a anotação@Query, conforme demonstrado na seção 2.2.

Outra opção é usar um construtor para criação de consulta customizada.

Por exemplo, podemos pesquisar artigos que tenham a palavra “data” no título criando uma consulta comNativeSearchQueryBuilder:

SearchQuery searchQuery = new NativeSearchQueryBuilder()
  .withFilter(regexpQuery("title", ".*data.*"))
  .build();
List
articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);

6. Atualizando e Excluindo

Para atualizar ou excluir um documento, primeiro precisamos recuperá-lo.

String articleTitle = "Spring Data Elasticsearch";
SearchQuery searchQuery = new NativeSearchQueryBuilder()
  .withQuery(matchQuery("title", articleTitle).minimumShouldMatch("75%"))
  .build();

List
articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);

Agora, para atualizar o título do artigo - podemos modificar o documento e usar a APIsave:

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

Como você deve ter imaginado, para excluir um documento, você pode usar o métododelete:

articleService.delete(articles.get(0));

7. Conclusão

Esta foi uma discussão rápida e prática do uso básico do Spring Data Elasticsearch.

Para ler mais sobre os recursos impressionantes do Elasticsearch, você pode encontrar seudocumentation no site oficial.

O exemplo usado neste artigo está disponível comosample project in GitHub.