Integrating Spring Data ElasticSearch

Keywords: Operation & Maintenance ElasticSearch Spring Java Redis

1. Overview

  • Spring Data ElasticSearch simplifies native ElasticSearch
  • Characteristic:
      1. Based on the @ Configuration configuration, as long as it is configured in the yml file, it can be used in the project.
      1. Tool class ElasticsearchTemplate ES template, similar to general mapper, operates ES through object
      1. Provides a Repository for the persistence layer interface, which is equivalent to using mapper

Comparison between elastic search and traditional database

Relational database (such as MySQL) Non relational database (Es)
Database Index Index
Table Table Type Type
Row Document
Data Column Field field

Basic concepts

Technical Term concept
Node (node) A single server with elastic search service and failover and expansion.
Cluster (cluster) A cluster is a cluster organized by one or more node s to work together and share the whole data with load balancing function.
Document A document is a basic unit of information that can be indexed.
Index (index) Index is a collection of documents with some similar characteristics.
Type (type) In an index, you can define one or more types.
Field (column) Field is the smallest unit of Elasticsearch, which is equivalent to a column of data.
Shards (shards) Elastic search divides the index into several parts, each of which is a shard.
Replicas (replication) Replicas is an index of one or more copies.

2. Setting up the environment

  • Create a sub module and learn elastic search

  • Step 1: modify pom.xml file and add corresponding coordinates. Add dependency for ES

    <dependencies>
            <!--redis-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
            </dependency>
            <!--test-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
            </dependency>
            <!--custom common-->
            <dependency>
                <groupId>com.czxy</groupId>
                <artifactId>changgou3_common</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
            <!--es-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
            </dependency>
    
        </dependencies>
    
  • Step 2: modify the yml file and add the relevant configuration of elastic search

     spring:
      redis:
        database:   1     #Confirm to use the library
        host: 127.0.0.1   #redis service address
        port: 6379      #redis port number
      data:
        elasticsearch:
          cluster-name: elasticsearch
          cluster-nodes: 127.0.0.1:9300
    
  • Step 3: add configuration class

package com.czxy.config;

import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

/**
 * @author Cloud before court
 * @Date 2020/4/13 20:38
 * @description
 */
@Configuration
public class ESConfig {
    @PostConstruct
    public void init(){
        System.setProperty("es.set.netty.runtime.available.processors","false");
    }
}

3. Index operation

3.1 mapping class

  • Mapping class: used to represent the data correspondence between java and elastic search. Using annotations in spring data elastic search.

    Annotated name describe
    @Document Used to configure the correspondence between Java class and index / type < br / > - indexname: corresponding index library name < br / > - type: corresponding type in index library < br / > - shards: partition quantity, default 5 < br / > - replicas: Replica quantity, default 1
    @Id Unique identification
    @Field Used to configure the field correspondence between Java attributes and es < br > – type: field type, enumeration: fieldtype < br > – analyzer: participator name < br > – index: index, boolean type, default is true < br > – store: store, boolean type, default is false
  • Realization

package com.czxy.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

/**
 * @author Cloud before court
 * @Date 2020/4/13 20:40
 * @description
 */
@Document(indexName = "czxy56",type = "book",shards = 4,replicas = 2)
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ESBook {
    @Id
    private Long id;

    @Field(type= FieldType.Text, analyzer = "ik_max_word")
    private String title;//Title

    @Field(type=FieldType.Keyword , index = true)
    private String images;//picture

    @Field(type=FieldType.Float)
    private Float price;//Price
}

3.2 create index, add mapping and delete index

  • The ElasticsearchTemplate tool class provides corresponding methods to complete the following functions:

    • Create index: createindex (mapping class. class)
    • Add mapping: putmapping (mapping class. class)
    • Delete index: deleteindex (mapping class. class)
  • 1, In the test class, inject ElasticsearchTemplate

  • 2, Call the corresponding API for operation

    package com.czxy.elasticsearch;
    
    import com.czxy.TestApplication;
    import com.czxy.vo.ESBook;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import javax.annotation.Resource;
    
    /**
     * @author Cloud before court
     * @Date 2020/4/13 20:33
     * @description
     */
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = TestApplication.class)
    public class TestES {
    
        @Resource
        private ElasticsearchTemplate elasticsearchTemplate;
    
    
        @Test
        public void demo01() {
            //Create the index according to the @ Document annotation information of class czxy56
            elasticsearchTemplate.createIndex(ESBook.class);
        }
    
        @Test
        public void demo02() {
            //The configuration mapping will be automatically completed according to the id, Field and other fields in the czxy56 class
            elasticsearchTemplate.putMapping(ESBook.class);
        }
    
        @Test
        public void demo03() {
            //Delete the map, which can be deleted according to the class name or index name
            elasticsearchTemplate.deleteIndex(ESBook.class);
        }
    }
    
    

4. Document operation (addition, deletion and modification)

4.1. Top level interface: Repository

  • Spring data elastic search provides a top-level interface Repository. You don't need to write any DAO processing, and automatically CRUD operations based on the method name or class information. As long as you define an interface and then inherit some sub interfaces provided by Repository, you can have various basic crud functions.

    • PagingAndSortingRepository: (second generation) complete paging and sorting functions
    • ElasticsearchCrudRepository: (the third generation) add, delete, modify and query function
    • Elastic search Repository: (fourth generation) complete all functions
  • Write: just write sub interface, inherit ElasticsearchRepository, and Spring Data will load the class automatically.

  • Note: when using the interface, you need to determine two generic information
    • First generic: mapping class, here is ESBook
    • The second generic type: the type uniquely identified by the mapping class, the type Long of the ID
package com.czxy.Repository;

import com.czxy.vo.ESBook;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import java.util.List;

/**
 * @author Cloud before court
 * @Date 2020/4/13 20:49
 * @description
 */
public interface ESBookRepository extends ElasticsearchRepository<ESBook, Long> {

}

4.2 add data

Method name describe
save(T t) Save a data
saveAll( Iterable ) Save a set of data
package com.czxy.elasticsearch;

import com.czxy.Repository.ESBookRepository;
import com.czxy.TestApplication;
import com.czxy.vo.ESBook;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.util.ArrayList;

/**
 * @author Cloud before court
 * @Date 2020/4/13 20:51
 * @description
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class TestData {

    @Resource
    private ESBookRepository esBookRepository;

    @Test
    public void demo01() {
        ESBook esBook = new ESBook(1L, "Test one", "1.jpg", 998f);
        //Add to
        esBookRepository.save(esBook);
    }

    @Test
    public void demo02() {
        ArrayList<ESBook> esBooks = new ArrayList<>();
        esBooks.add(new ESBook(2L, "Test two", "2.jpg", 456f));
        esBooks.add(new ESBook(3L, "Test three", "3.jpg", 290f));
        esBooks.add(new ESBook(4L, "Test four", "4.jpg", 100f));
        //Add a set of data  
        esBookRepository.saveAll(esBooks);
    }
}

4.3 modify data

  • Modify and add using the same method

  • Differentiation criteria:

    • If the value of id has corresponding data, update is performed.
    • If the value of id does not have corresponding data, add.
        @Test
        public void demo03() {
            //Update data. There must be data with id=1 in es
            ESBook esBook = new ESBook(1L, "Test change", "1111.jpg", 1998f);
            esBookRepository.save(esBook);
        }
    

4.3 delete data

  @Test
    public void demo04() {
        ESBook esBook = new ESBook();
        esBook.setId(1L);
        esBookRepository.delete(esBook);
    }

4.4, query

Method describe
findAll() Query all
findById( Long ) Query details by id
package com.czxy.elasticsearch;

import com.czxy.Repository.ESBookRepository;
import com.czxy.TestApplication;
import com.czxy.vo.ESBook;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;

/**
 * @author Cloud before court
 * @Date 2020/4/13 21:01
 * @description
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class TestESFind {
    @Resource
    private ESBookRepository esBookRepository;

    @Test
    public void demo01() {
        //Query all
        Iterable<ESBook> iterable = esBookRepository.findAll();
        Iterator<ESBook> iterator = iterable.iterator();
        while (iterator.hasNext()) {
            ESBook esBook = iterator.next();
            System.out.println(esBook);
        }
    }

    @Test
    public void demo02() {
        //Query details by id
        Optional<ESBook> optional = esBookRepository.findById(2L);
        ESBook esBook = optional.get();
        System.out.println(esBook);
    }
}

4.5 user defined method query

  • Custom query: Spring Data queries automatically according to the agreed method name.
    • Contract method name requirements: findBy field name | keyword, etc
    • For example: findbytitle (value) queries by title
Keyword Sample Elasticsearch Query String
And findByNameAndPrice {"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
Or findByNameOrPrice {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
Is findByName {"bool" : {"must" : {"field" : {"name" : "?"}}}}
Not findByNameNot {"bool" : {"must_not" : {"field" : {"name" : "?"}}}}
Between findByPriceBetween {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
LessThanEqual findByPriceLessThan {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
GreaterThanEqual findByPriceGreaterThan {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
Before findByPriceBefore {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
After findByPriceAfter {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
Like findByNameLike {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
StartingWith findByNameStartingWith {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
EndingWith findByNameEndingWith {"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}}
Contains/Containing findByNameContaining {"bool" : {"must" : {"field" : {"name" : {"query" : "**?**","analyze_wildcard" : true}}}}}
In findByNameIn(Collection<String>names) {"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}}
NotIn findByNameNotIn(Collection<String>names) {"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}}
Near findByStoreNear Not Supported Yet !
True findByAvailableTrue {"bool" : {"must" : {"field" : {"available" : true}}}}
False findByAvailableFalse {"bool" : {"must" : {"field" : {"available" : false}}}}
OrderBy findByAvailableTrueOrderByNameDesc {"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}}
  • Example 1: query by title

      1. Modify response custom interface and add method declaration
      package com.czxy.Repository;
      
      import com.czxy.vo.ESBook;
      import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
      
      import java.util.List;
      
      /**
       * @author Cloud before court
       * @Date 2020/4/13 20:49
       * @description
       */
      public interface ESBookRepository extends ElasticsearchRepository<ESBook, Long> {
          //Example 1: query by title
          public List<ESBook> findByTitle(String title);
      }
      
      
      1. Call custom method to complete function
          @Test
          public void demo03() {
              List<ESBook> list = esBookRepository.findByTitle("Test two");
              System.out.println(list);
          }
      
  • Example 2: interval query, price 50-300

      1. statement
           //Example 2: interval query, price 50-300
          public List<ESBook> findByPriceBetween(Float start, Float end);
      
      1. call
          @Test
          public void demo04() {
              List<ESBook> list = esBookRepository.findByPriceBetween(50f, 300f);
              System.out.println(list);
          }
      
  • Example 3: query price > = 290

      1. statement
          //Example 3: query price > = 290
          public List<ESBook> findByPriceGreaterThanEqual(Float price);
      
      
      1. call
          @Test
          public void demo05(){
              List<ESBook> list = esBookRepository.findByPriceGreaterThanEqual(290f);
              System.out.println(list);
          }
      
  • Example 4: interval query, price 50-300, and sorting by images in descending order

      1. statement
      //Example 4: interval query, price 50-300, and sorted in descending order by image 
      public List<ESBook> findByPriceBetweenOrderByImagesDesc(Float start, Float end);
      
      
      1. call
          @Test
          public void demo06(){
              List<ESBook> list = esBookRepository.findByPriceBetweenOrderByImagesDesc(50f,300f);
              System.out.println(list);
          }
      
      

Posted by Svoboda on Mon, 13 Apr 2020 21:14:09 -0700