zoukankan      html  css  js  c++  java
  • Spring Boot 集成 Elasticsearch

    原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/15229906.html

    Project Directory

    Maven Dependency

    <?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>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.12.RELEASE</version>
            <relativePath/>
        </parent>
    
        <groupId>org.fool.es</groupId>
        <artifactId>hello-spring-data-es</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
    </project>
    View Code

    application.properties

    server.port=8080
    
    logging.level.org.fool.es=debug
    
    elasticsearch.host=127.0.0.1
    elasticsearch.port=9200

    SRC

    Application.java

    package org.fool.es;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }

    ElasticsearchConfig.java

    package org.fool.es.config;
    
    import lombok.Data;
    import lombok.EqualsAndHashCode;
    import org.apache.http.HttpHost;
    import org.elasticsearch.client.RestClient;
    import org.elasticsearch.client.RestHighLevelClient;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
    
    @ConfigurationProperties(prefix = "elasticsearch")
    @Configuration
    @Data
    @EqualsAndHashCode(callSuper = true)
    public class ElasticsearchConfig extends AbstractElasticsearchConfiguration {
        private String host;
        private Integer port;
    
        @Override
        public RestHighLevelClient elasticsearchClient() {
            return new RestHighLevelClient(RestClient.builder(new HttpHost(host, port)));
        }
    }

    使用 ElasticsearchRepository 进行通用的 CRUD

    Product.java

    package org.fool.es.index;
    
    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;
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Document(indexName = "product", shards = 1, replicas = 1)
    public class Product {
        @Id
        private Long id;
        @Field(type = FieldType.Text, analyzer = "ik_max_word")
        private String title;
        @Field(type = FieldType.Keyword)
        private String category;
        @Field(type = FieldType.Double)
        private Double price;
        @Field(type = FieldType.Keyword, index = false)
        private String imageUrl;
    }

    ProductDAO.java

    package org.fool.es.dao;
    
    import org.fool.es.index.Product;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    
    @Repository
    public interface ProductDAO extends ElasticsearchRepository<Product, Long> {
        List<Product> findByTitle(String title);
    
        List<Product> findByTitle(String title, Pageable pageable);
    
        List<Product> findByTitleAndCategory(String title, String category);
    
        List<Product> findByTitleOrCategory(String title, String category);
    
    }

    SpringDataESTest.java

    package org.fool.es.test;
    
    import org.fool.es.dao.ProductDAO;
    import org.fool.es.index.Product;
    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.data.domain.PageRequest;
    import org.springframework.data.domain.Sort;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.util.ArrayList;
    import java.util.List;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class SpringDataESTest {
    
        @Autowired
        private ProductDAO productDAO;
    
        ......
    }

    insert

    @Test
    public void testInsert() {
        Product product = new Product();
        product.setId(1001L);
        product.setTitle("iPhone X");
        product.setCategory("mobile");
        product.setPrice(6999.0);
        product.setImageUrl("http://www.apple.com/iPhone.jpg");
        productDAO.save(product);
    }

    update

    @Test
    public void testUpdate() {
        Product product = new Product();
        product.setId(1001L);
        product.setTitle("iPhone X Max");
        product.setCategory("mobile");
        product.setPrice(8999.0);
        product.setImageUrl("http://www.apple.com/iPhone.jpg");
        productDAO.save(product);
    }

    delete

    @Test
    public void testDelete() {
        Product product = new Product();
        product.setId(1001L);
        productDAO.delete(product);
    }

    batchInsert

    @Test
    public void testBatchInsert() {
        List<Product> productList = new ArrayList<>();
    
        for (int i = 0; i < 10; i++) {
            Product product = new Product();
            product.setId((long) i);
            product.setTitle("iPhone " + i);
            product.setCategory("mobile");
            product.setPrice(6999.0 + i);
            product.setImageUrl("http://www.apple.com/iPhone.jpg");
            productList.add(product);
        }
    
        productDAO.saveAll(productList);
    }

    findById

    @Test
    public void testFindById() {
        productDAO.findById(1001L).ifPresent(System.out::println);
    }

    findAll

    @Test
    public void testFindAll() {
        productDAO.findAll().forEach(System.out::println);
    }

    findByPageable

    @Test
    public void findByPageable() {
        Sort sort = Sort.by(Sort.Direction.DESC, "id");
        int currentPage = 0;
        int pageSize = 5;
    
        PageRequest pageRequest = PageRequest.of(currentPage, pageSize, sort);
    
        Page<Product> results = productDAO.findAll(pageRequest);
    
        System.out.println(results.getTotalPages());
        System.out.println(results.getSize());
        System.out.println(results.getNumber());
    
        results.getContent().forEach(System.out::println);
    }

    findByTitle

    @Test
    public void testFindByTitle() {
        productDAO.findByTitle("iPhone 8").forEach(System.out::println);
    }

    findByTitleWithPagination

    @Test
    public void testFindByTitleWithPagination() {
        productDAO.findByTitle("iPhone", PageRequest.of(0, 5)).forEach(System.out::println);
    }

    findByTitleOrCategory

    @Test
    public void testFindByTitleOrCategory() {
        productDAO.findByTitleOrCategory("iPhone", "mobile").forEach(System.out::println);
    }

    findByTitleAndCategory

    @Test
    public void testFindByTitleAndCategory() {
        productDAO.findByTitleAndCategory("iPhone", "pad").forEach(System.out::println);
    }

    使用 NativeSearchQuery 进行复杂查询

    User.java

    package org.fool.es.index;
    
    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;
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Document(indexName = "user", shards = 1, replicas = 1)
    public class User {
        @Id
        private Long id;
        @Field(type = FieldType.Text, analyzer = "ik_max_word")
        private String name;
        @Field(type = FieldType.Keyword)
        private String sex;
        @Field(type = FieldType.Integer)
        private Integer age;
        @Field(type = FieldType.Text, analyzer = "ik_max_word")
        private String address;
    }

    UserDAO.java

    package org.fool.es.dao;
    
    import org.fool.es.index.User;
    import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface UserDAO extends ElasticsearchRepository<User, Long> {
    
    }

    SpringESNativeSearchQueryTest.java

    package org.fool.es.test;
    
    import org.elasticsearch.common.unit.Fuzziness;
    import org.elasticsearch.index.query.MatchAllQueryBuilder;
    import org.elasticsearch.index.query.QueryBuilders;
    import org.elasticsearch.search.aggregations.AggregationBuilders;
    import org.elasticsearch.search.aggregations.Aggregations;
    import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
    import org.elasticsearch.search.aggregations.bucket.terms.Terms;
    import org.elasticsearch.search.aggregations.metrics.ParsedMax;
    import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
    import org.elasticsearch.search.sort.SortBuilders;
    import org.elasticsearch.search.sort.SortOrder;
    import org.fool.es.dao.UserDAO;
    import org.fool.es.index.User;
    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.PageRequest;
    import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
    import org.springframework.data.elasticsearch.core.SearchHit;
    import org.springframework.data.elasticsearch.core.SearchHits;
    import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
    import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
    import org.springframework.data.elasticsearch.core.query.SourceFilter;
    import org.springframework.test.context.junit4.SpringRunner;
    
    import java.util.ArrayList;
    import java.util.List;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class SpringESNativeSearchQueryTest {
    
        @Autowired
        private UserDAO userDAO;
    
        @Autowired
        private ElasticsearchRestTemplate elasticsearchRestTemplate;
    
        @Test
        public void testBatchInsert() throws Exception {
            List<User> recordList = new ArrayList<>();
            recordList.add(new User(1001L, "caocao", "male", 10, "shanghai"));
            recordList.add(new User(1002L, "liubei", "male", 20, "beijing"));
            recordList.add(new User(1003L, "sunquan", "male", 30, "shenzhen"));
            recordList.add(new User(1004L, "guanyu", "male", 40, "guangzhou"));
            recordList.add(new User(1005L, "zhangfei", "male", 40, "shanghai"));
            recordList.add(new User(1006L, "zhaoyun", "male", 50, "beijing"));
            recordList.add(new User(1007L, "caocao2", "female", 50, "chengdu"));
    
            userDAO.saveAll(recordList);
        }
    
        @Test
        public void testDelete() {
            userDAO.deleteAll();
        }
    
        ......
    
    }

    Note:

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    queryAll

    @Test
    public void testQueryAll() {
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(new MatchAllQueryBuilder())
                .build();
    
        SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class);
    
        long count = searchHits.getTotalHits();
        System.out.println(count);
        List<SearchHit<User>> list = searchHits.getSearchHits();
        for (SearchHit<User> record : list) {
            System.out.println(record.getContent());
        }
    }

    queryString

    @Test
    public void testQueryString() {
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                // query field address
                .withQuery(QueryBuilders.queryStringQuery("shanghai").defaultField("address"))
                // query all field
                //.withQuery(QueryBuilders.queryStringQuery("shanghai"))
                // query field name, address
                //.withQuery(QueryBuilders.queryStringQuery("shanghai").field("name").field("address"))
                .build();
    
        SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class);
    
        long count = searchHits.getTotalHits();
        System.out.println(count);
        List<SearchHit<User>> list = searchHits.getSearchHits();
        for (SearchHit<User> record : list) {
            System.out.println(record.getContent());
        }
    }

    queryTerm

    @Test
    public void testQueryTerm() {
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.termQuery("name", "caocao"))
                .build();
    
        SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class);
    
        long count = searchHits.getTotalHits();
        System.out.println(count);
        List<SearchHit<User>> list = searchHits.getSearchHits();
        for (SearchHit<User> record : list) {
            System.out.println(record.getContent());
        }
    }

    queryPagination

    @Test
    public void testQueryPagination() {
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchAllQuery())
                .withPageable(PageRequest.of(0, 5))
                .build();
    
        SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class);
    
        long count = searchHits.getTotalHits();
        System.out.println(count);
        List<SearchHit<User>> list = searchHits.getSearchHits();
        for (SearchHit<User> record : list) {
            System.out.println(record.getContent());
        }
    }

    querySort

    @Test
    public void testQuerySort() {
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchAllQuery())
                .withPageable(PageRequest.of(0, 5))
                .withSort(SortBuilders.fieldSort("id").order(SortOrder.DESC))
                .build();
    
        SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class);
    
        long count = searchHits.getTotalHits();
        System.out.println(count);
        List<SearchHit<User>> list = searchHits.getSearchHits();
        for (SearchHit<User> record : list) {
            System.out.println(record.getContent());
        }
    }

    queryFilter

    @Test
    public void testQueryFilter() {
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchAllQuery())
                .withPageable(PageRequest.of(0, 5))
                .withSourceFilter(new SourceFilter() {
                    @Override
                    public String[] getIncludes() {
                        return new String[]{"name"};
                    }
    
                    @Override
                    public String[] getExcludes() {
                        return new String[]{};
                    }
                }).build();
    
        SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class);
    
        long count = searchHits.getTotalHits();
        System.out.println(count);
        List<SearchHit<User>> list = searchHits.getSearchHits();
        for (SearchHit<User> record : list) {
            System.out.println(record.getContent());
        }
    }

    queryBool

    @Test
    public void testQueryBool() {
        // or
        //NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
        //        .withQuery(QueryBuilders.boolQuery()
        //                .should(QueryBuilders.termQuery("age", 30))
        //                .should(QueryBuilders.termQuery("sex", "female")))
        //        .build();
    
        // and
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.boolQuery()
                        .must(QueryBuilders.termQuery("age", 30))
                        .must(QueryBuilders.termQuery("sex", "male")))
                .build();
    
        SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class);
    
        long count = searchHits.getTotalHits();
        System.out.println(count);
        List<SearchHit<User>> list = searchHits.getSearchHits();
        for (SearchHit<User> record : list) {
            System.out.println(record.getContent());
        }
    }

    queryRange

    @Test
    public void testQueryRange() {
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.rangeQuery("age").gte(30).lte(50))
                .build();
    
        SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class);
    
        long count = searchHits.getTotalHits();
        System.out.println(count);
        List<SearchHit<User>> list = searchHits.getSearchHits();
        for (SearchHit<User> record : list) {
            System.out.println(record.getContent());
        }
    }

    queryFuzzy

    @Test
    public void testQueryFuzzy() {
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.fuzzyQuery("name", "caocao").fuzziness(Fuzziness.ONE))
                .build();
    
        SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class);
    
        long count = searchHits.getTotalHits();
        System.out.println(count);
        List<SearchHit<User>> list = searchHits.getSearchHits();
        for (SearchHit<User> record : list) {
            System.out.println(record.getContent());
        }
    }

    queryHighlight

    @Test
    public void testQueryHighlight() {
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.termQuery("name", "caocao"))
                .withHighlightFields(new HighlightBuilder.Field("name").preTags("<font color='red'>").postTags("</font>"))
                .build();
    
        SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class);
    
        long count = searchHits.getTotalHits();
        System.out.println(count);
        List<SearchHit<User>> list = searchHits.getSearchHits();
        for (SearchHit<User> record : list) {
            System.out.println(record.getContent());
            System.out.println(record.getHighlightFields());
        }
    }

    queryAggregation

    @Test
    public void testQueryAggregation() {
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .addAggregation(AggregationBuilders.max("maxAge").field("age"))
                .build();
    
        SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class);
    
        long count = searchHits.getTotalHits();
        System.out.println(count);
    
        Aggregations aggregations = searchHits.getAggregations();
        assert aggregations != null;
        ParsedMax terms = aggregations.get("maxAge");
        System.out.println(terms.getValue());
    }

    queryGroup

    @Test
    public void testQueryGroup() {
        NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
                .addAggregation(AggregationBuilders.terms("ageGroup").field("age"))
                .build();
    
        SearchHits<User> searchHits = elasticsearchRestTemplate.search(nativeSearchQuery, User.class);
    
        long count = searchHits.getTotalHits();
        System.out.println(count);
    
        Aggregations aggregations = searchHits.getAggregations();
        assert aggregations != null;
        ParsedLongTerms terms = aggregations.get("ageGroup");
        List<? extends Terms.Bucket> buckets = terms.getBuckets();
        for (Terms.Bucket bucket : buckets) {
            System.out.println(bucket.getKey() + ":" + bucket.getDocCount());
        }
    }

    Reference

    https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.repositories


    欢迎点赞关注和收藏

    强者自救 圣者渡人
  • 相关阅读:
    Java 集合系列16之 HashSet详细介绍(源码解析)和使用示例
    Java 集合系列15之 Set架构
    Java 集合系列14之 Map总结(HashMap, Hashtable, TreeMap, WeakHashMap等使用场景)
    Java 集合系列13之 WeakHashMap详细介绍(源码解析)和使用示例
    Java 集合系列13之 TreeMap详细介绍(源码解析)和使用示例
    Java 集合系列12之 Hashtable详细介绍(源码解析)和使用示例
    Java 集合系列11之 HashMap详细介绍(二)
    Java 集合系列10之 HashMap详细介绍(源码解析)和使用示例
    Maven01-maven打包Web项目成war文件-tomcat脱机运行启动项目
    Spring -13 -Spring 中常用注解总结
  • 原文地址:https://www.cnblogs.com/agilestyle/p/15229906.html
Copyright © 2011-2022 走看看