Spring Boot & ES is worth reference!

Keywords: Java ElasticSearch Spring Maven

Author: Waste senior brother
cnblogs.com/cjsblog/p/9756978.html

1. Preface

1.1. Integration mode

There are four ways to integrate Elasticsearch in Spring Boot:

  • REST Client

  • Jest

  • Spring Data

  • Spring Data Elasticsearch Repositories

This paper uses the following two methods to connect and operate elastic search respectively

1.2. Environment and configuration

Server: elastic search-6.3.2 1

Client: elastic search 6.4.1

Server profile: elasticsearch.yml

cluster.name: my-application
network.host: 192.168.1.134
http.port: 9200

/etc/security/limits.conf

cheng soft nofile 65536
cheng hard nofile 65536

/etc/sysctl.conf

vm.max\_map\_count=262144

1.3. Version

The default elastic search version of Spring Boot 2.0.5 is very low. Here we use the latest version 6.4.1

If during startup

java.lang.NoClassDefFoundError: org/elasticsearch/common/transport/InetSocketTransportAddress

It means that the versions of the jar packages relied on by elastic search are inconsistent, just change to 6.4.1

In addition, the spring data elastic search version that Spring Boot 2.0.5 relies on is 3.0.1, which needs to be upgraded to 3.1.0

2. Dependence

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.cjs.example</groupId>
    <artifactId>cjs-elasticsearch-example</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>cjs-elasticsearch-example</name>
    <description></description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>

        <elasticsearch.version>6.4.1</elasticsearch.version>
        <spring.data.elasticsearch.version>3.1.0.RELEASE</spring.data.elasticsearch.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>${elasticsearch.version}</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>transport</artifactId>
            <version>${elasticsearch.version}</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>${elasticsearch.version}</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.plugin</groupId>
            <artifactId>transport-netty4-client</artifactId>
            <version>${elasticsearch.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-elasticsearch</artifactId>
            <version>${spring.data.elasticsearch.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

3. application.properties

spring.data.elasticsearch.cluster-name=my-application
spring.data.elasticsearch.cluster-nodes=192.168.1.134:9300

Maybe, you will wonder, the port written in the configuration file is 9200. Why is the port written in the configuration file 9300 when connecting?

Because, the configuration 9200 is the port that connects through HTTP, and 9300 is the port that connects through TCP

4. Operation

4.1. Use Spring Data Elasticsearch Repositories to operate Elasticsearch

First, define an entity class

package com.cjs.example.entity;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;

import java.io.Serializable;

@Data
@Document(indexName = "commodity")
public class Commodity implements Serializable {

    @Id
    private String skuId;

    private String name;

    private String category;

    private Integer price;

    private String brand;

    private Integer stock;

}

The Commodity instance is defined here to represent the Commodity. In elasticsearch version 6. X, type is not recommended, and will be completely discarded in version 7.X, so I only specified indexName here, not type.

Here, a Commodity represents a Commodity and an index record.

Compared with relational database, Index is equivalent to table and Document is equivalent to record. Then, you need to define an interface and inherit elastic search repository.

package com.cjs.example.dao;

import com.cjs.example.entity.Commodity;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface CommodityRepository extends ElasticsearchRepository<Commodity, String> {

}

The Repository here is equivalent to DAO, and the operation of mysql or elastic search is the same

Next, define the service interface

package com.cjs.example.service;

import com.cjs.example.entity.Commodity;
import org.springframework.data.domain.Page;

import java.util.List;

public interface CommodityService {

    long count();

    Commodity save(Commodity commodity);

    void delete(Commodity commodity);

    Iterable<Commodity> getAll();

    List<Commodity> getByName(String name);

    Page<Commodity> pageQuery(Integer pageNo, Integer pageSize, String kw);

}

Implementation class

package com.cjs.example.service.impl;

import com.cjs.example.entity.Commodity;
import com.cjs.example.dao.CommodityRepository;
import com.cjs.example.service.CommodityService;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class CommodityServiceImpl implements CommodityService {

    @Autowired
    private CommodityRepository commodityRepository;

    @Override
    public long count() {
        return commodityRepository.count();
    }

    @Override
    public Commodity save(Commodity commodity) {
        return commodityRepository.save(commodity);
    }

    @Override
    public void delete(Commodity commodity) {
        commodityRepository.delete(commodity);
//        commodityRepository.deleteById(commodity.getSkuId());
    }

    @Override
    public Iterable<Commodity> getAll() {
        return commodityRepository.findAll();
    }

    @Override
    public List<Commodity> getByName(String name) {
        List<Commodity> list = new ArrayList<>();
        MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("name", name);
        Iterable<Commodity> iterable = commodityRepository.search(matchQueryBuilder);
        iterable.forEach(e->list.add(e));
        return list;
    }

    @Override
    public Page<Commodity> pageQuery(Integer pageNo, Integer pageSize, String kw) {
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchPhraseQuery("name", kw))
                .withPageable(PageRequest.of(pageNo, pageSize))
                .build();
        return commodityRepository.search(searchQuery);
    }

}

In this Service, the operation of adding, deleting, querying and modifying is demonstrated, as well as pagination query

Finally, write a test class to test its methods

package com.cjs.example;

import com.cjs.example.entity.Commodity;
import com.cjs.example.service.CommodityService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
public class CjsElasticsearchExampleApplicationTests {

    @Autowired
    private CommodityService commodityService;

    @Test
    public void contextLoads() {
        System.out.println(commodityService.count());
    }

    @Test
    public void testInsert() {
        Commodity commodity = new Commodity();
        commodity.setSkuId("1501009001");
        commodity.setName("Original sliced bread (10 slices)");
        commodity.setCategory("101");
        commodity.setPrice(880);
        commodity.setBrand("Good shop");
        commodityService.save(commodity);

        commodity = new Commodity();
        commodity.setSkuId("1501009002");
        commodity.setName("Original sliced bread (6 pieces)");
        commodity.setCategory("101");
        commodity.setPrice(680);
        commodity.setBrand("Good shop");
        commodityService.save(commodity);

        commodity = new Commodity();
        commodity.setSkuId("1501009004");
        commodity.setName("Yuanqi toast 850 g");
        commodity.setCategory("101");
        commodity.setPrice(120);
        commodity.setBrand("Herb flavor");
        commodityService.save(commodity);

    }

    @Test
    public void testDelete() {
        Commodity commodity = new Commodity();
        commodity.setSkuId("1501009002");
        commodityService.delete(commodity);
    }

    @Test
    public void testGetAll() {
        Iterable<Commodity> iterable = commodityService.getAll();
        iterable.forEach(e->System.out.println(e.toString()));
    }

    @Test
    public void testGetByName() {
        List<Commodity> list = commodityService.getByName("bread");
        System.out.println(list);
    }

    @Test
    public void testPage() {
        Page<Commodity> page = commodityService.pageQuery(0, 10, "section");
        System.out.println(page.getTotalPages());
        System.out.println(page.getNumber());
        System.out.println(page.getContent());
    }
}

This is how to use elastic search repositories

4.2. Use ElasticsearchTemplate to operate Elasticsearch

package com.cjs.example;

import com.cjs.example.entity.Commodity;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ElasticsearchTemplateTest {

    @Autowired
    public ElasticsearchTemplate elasticsearchTemplate;

    @Test
    public void testInsert() {
        Commodity commodity = new Commodity();
        commodity.setSkuId("1501009005");
        commodity.setName("Grape toast (10 slices)");
        commodity.setCategory("101");
        commodity.setPrice(160);
        commodity.setBrand("Good shop");

        IndexQuery indexQuery = new IndexQueryBuilder().withObject(commodity).build();
        elasticsearchTemplate.index(indexQuery);
    }

    @Test
    public void testQuery() {
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchQuery("name", "toast"))
                .build();
        List<Commodity> list = elasticsearchTemplate.queryForList(searchQuery, Commodity.class);
        System.out.println(list);
    }

}

ElasticsearchTemplate is automatically configured

5. Demonstration

6. Engineering structure

7. Reference

https://docs.spring.io/spring-data/elasticsearch/docs/3.1.0.RELEASE/reference/html/#repositories.query-methods.details

Recommend to my blog to read more:

1.Java JVM, collection, multithreading, new features series

2.Spring MVC, Spring Boot, Spring Cloud series tutorials

3.Maven, Git, Eclipse, Intellij IDEA series tools tutorial

4.Latest interview questions of Java, backend, architecture, Alibaba and other large factories

Feel good, don't forget to like + forward!

Posted by MemphiS on Fri, 19 Jun 2020 04:14:44 -0700