├── src ├── main │ ├── java │ │ └── com │ │ │ └── zbq │ │ │ └── springbootelasticsearch │ │ │ ├── dao │ │ │ ├── package-info.java │ │ │ └── GoodsESDao.java │ │ │ ├── common │ │ │ ├── package-info.java │ │ │ ├── exception │ │ │ │ ├── IApiResponseCode.java │ │ │ │ ├── ElasticsearchException.java │ │ │ │ ├── ApiResponseCode.java │ │ │ │ └── ApiException.java │ │ │ ├── enums │ │ │ │ └── ElasticsearchIndexEnum.java │ │ │ ├── elasticsearch │ │ │ │ ├── annotation │ │ │ │ │ ├── ESId.java │ │ │ │ │ ├── ESField.java │ │ │ │ │ └── ESDocument.java │ │ │ │ ├── enums │ │ │ │ │ └── ESFieldType.java │ │ │ │ └── base │ │ │ │ │ ├── ESPageResult.java │ │ │ │ │ ├── ESPageRequest.java │ │ │ │ │ ├── ESSort.java │ │ │ │ │ ├── BaseElasticsearchDao.java │ │ │ │ │ └── ElasticsearchUtils.java │ │ │ └── config │ │ │ │ ├── ElasticsearchProperties.java │ │ │ │ ├── ElasticsearchApplicationListener.java │ │ │ │ └── ElasticsearchConfig.java │ │ │ ├── SpringBootElasticsearchApplication.java │ │ │ └── model │ │ │ └── GoodsESEntity.java │ └── resources │ │ └── application.yml └── test │ └── java │ └── com │ └── zbq │ └── springbootelasticsearch │ ├── SpringBootElasticsearchApplicationTests.java │ ├── ElasticSearchTest.java │ └── GoodsESDaoTest.java ├── .gitignore └── pom.xml /src/main/java/com/zbq/springbootelasticsearch/dao/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author zhangboqing 3 | * @date 2019/12/10 4 | */ 5 | package com.zbq.springbootelasticsearch.dao; -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author zhangboqing 3 | * @date 2019/12/10 4 | */ 5 | package com.zbq.springbootelasticsearch.common; -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/exception/IApiResponseCode.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.common.exception; 2 | 3 | /** 4 | * @author zhangboqing 5 | * @date 2019/12/10 6 | */ 7 | public interface IApiResponseCode { 8 | Integer getCode(); 9 | 10 | String getMessage(); 11 | } 12 | -------------------------------------------------------------------------------- /src/test/java/com/zbq/springbootelasticsearch/SpringBootElasticsearchApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringBootElasticsearchApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/exception/ElasticsearchException.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.common.exception; 2 | 3 | 4 | /** 5 | * @author zhangboqing 6 | * @date 2019/12/10 7 | */ 8 | public class ElasticsearchException extends ApiException { 9 | 10 | public ElasticsearchException(String message) { 11 | super(ApiResponseCode.FAILED,message); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | demo: 2 | data: 3 | elasticsearch: 4 | # es集群名称 5 | cluster-name: elasticsearch 6 | # es集群节点,多个逗号分隔 localhost:9200,localhost:9400 7 | cluster-nodes: localhost:9200 8 | # 设置创建index时,默认的分片规则 9 | index: 10 | number-of-shards: 3 11 | number-of-replicas: 2 12 | # 设置连接es的用户名和密码 13 | account: 14 | username: elastic 15 | password: 123456 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | .mvn/ 25 | mvnw 26 | mvnw.cmd 27 | HELP.md 28 | .idea/ 29 | spring-boot-elasticsearch.iml 30 | target/ 31 | *.iml -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/SpringBootElasticsearchApplication.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBootElasticsearchApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringBootElasticsearchApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/enums/ElasticsearchIndexEnum.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.common.enums; 2 | 3 | /** 4 | * @author zhangboqing 5 | * @date 2019/12/10 6 | */ 7 | public enum ElasticsearchIndexEnum { 8 | /** 商品 */ 9 | GOODS("goods"); 10 | 11 | ElasticsearchIndexEnum(String indexName) { 12 | this.indexName = indexName; 13 | } 14 | 15 | private String indexName; 16 | 17 | public String getIndexName() { 18 | return indexName; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/elasticsearch/annotation/ESId.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.common.elasticsearch.annotation; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | import java.lang.annotation.Target; 6 | 7 | import static java.lang.annotation.ElementType.*; 8 | 9 | /** 10 | * @author zhangboqing 11 | * @date 2019/12/12 12 | */ 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Target(value = { FIELD, METHOD, ANNOTATION_TYPE }) 15 | public @interface ESId { 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/elasticsearch/enums/ESFieldType.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.common.elasticsearch.enums; 2 | 3 | /** 4 | * @author zhangboqing 5 | * @date 2019/12/12 6 | */ 7 | public enum ESFieldType { 8 | Text("text"), 9 | Byte("byte"), 10 | Short("short"), 11 | Integer("integer"), 12 | Long("long"), 13 | Date("date"), 14 | Float("float"), 15 | Double("double"), 16 | Boolean("boolean"), 17 | Object("object"), 18 | Keyword("keyword"); 19 | 20 | 21 | ESFieldType(String typeName) { 22 | this.typeName = typeName; 23 | } 24 | 25 | public String typeName; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/elasticsearch/base/ESPageResult.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.common.elasticsearch.base; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @Author zhangboqing 10 | * @Date 2019-12-30 11 | * 分页结果 12 | */ 13 | @Data 14 | public class ESPageResult { 15 | 16 | private final long total; 17 | private final int pageNo; 18 | private final int pageSize; 19 | private List results; 20 | 21 | public ESPageResult(long total, int pageNo, int pageSize, List results) { 22 | this.total = total; 23 | this.pageNo = pageNo; 24 | this.pageSize = pageSize; 25 | this.results = results; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/elasticsearch/annotation/ESField.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.common.elasticsearch.annotation; 2 | 3 | import com.zbq.springbootelasticsearch.common.elasticsearch.enums.ESFieldType; 4 | import org.springframework.core.annotation.AliasFor; 5 | 6 | import java.lang.annotation.*; 7 | 8 | /** 9 | * @author zhangboqing 10 | * @date 2019/12/12 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target(ElementType.FIELD) 14 | @Documented 15 | @Inherited 16 | public @interface ESField { 17 | 18 | @AliasFor("name") 19 | String value() default ""; 20 | 21 | @AliasFor("value") 22 | String name() default ""; 23 | 24 | ESFieldType type(); 25 | 26 | String analyzer() default ""; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/exception/ApiResponseCode.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.common.exception; 2 | 3 | public enum ApiResponseCode implements IApiResponseCode { 4 | SUCCESS(0, "成功"), 5 | FAILED(1, "失败"); 6 | 7 | public Integer code; 8 | public String message; 9 | 10 | @Override 11 | public Integer getCode() { 12 | return this.code; 13 | } 14 | 15 | @Override 16 | public String getMessage() { 17 | return this.message; 18 | } 19 | 20 | private ApiResponseCode(Integer code, String message) { 21 | this.code = code; 22 | this.message = message; 23 | } 24 | 25 | public String toString() { 26 | return "ApiResponseCode(code=" + this.getCode() + ", message=" + this.getMessage() + ")"; 27 | } 28 | } -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/elasticsearch/base/ESPageRequest.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.common.elasticsearch.base; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * 分页 7 | * @author zhangboqing 8 | * @date 2019/12/29 9 | */ 10 | @Data 11 | public class ESPageRequest { 12 | 13 | private final int pageNo; 14 | private final int size; 15 | 16 | public ESPageRequest(int pageNo, int size) { 17 | 18 | if (pageNo < 0) { 19 | throw new IllegalArgumentException("Page index must not be less than zero!"); 20 | } 21 | 22 | if (size < 1) { 23 | throw new IllegalArgumentException("Page size must not be less than one!"); 24 | } 25 | 26 | this.pageNo = pageNo; 27 | this.size = size; 28 | } 29 | 30 | 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/elasticsearch/annotation/ESDocument.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.common.elasticsearch.annotation; 2 | 3 | 4 | import java.lang.annotation.*; 5 | 6 | /** 7 | * @author zhangboqing 8 | * @date 2019/12/12 9 | */ 10 | @Inherited 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target({ ElementType.TYPE }) 13 | public @interface ESDocument { 14 | 15 | /** 16 | * Name of the Elasticsearch index. 17 | *
    18 | *
  • Lowercase only
  • 19 | *
  • , |, ` ` (space character), ,, #/li> 20 | *
  • Cannot start with -, _, +
  • 21 | *
  • Cannot be . or ..
  • 22 | *
  • Cannot be longer than 255 bytes (note it is bytes, so multi-byte characters will count towards the 255 limit 23 | * faster)
  • 24 | *
25 | */ 26 | String indexName(); 27 | 28 | /** 29 | * Number of shards for the index {@link #indexName()}. Used for index creation. 30 | */ 31 | int shards() default 0; 32 | 33 | /** 34 | * Number of replicas for the index {@link #indexName()}. Used for index creation. 35 | */ 36 | int replicas() default 0; 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/elasticsearch/base/ESSort.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.common.elasticsearch.base; 2 | 3 | import lombok.Builder; 4 | import lombok.Data; 5 | import org.elasticsearch.search.sort.SortOrder; 6 | import org.springframework.lang.Nullable; 7 | import org.springframework.util.Assert; 8 | 9 | import java.io.Serializable; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | import java.util.Locale; 13 | import java.util.Optional; 14 | import java.util.stream.Collectors; 15 | 16 | /** 17 | * @Author zhangboqing 18 | * @Date 2019/12/29 19 | * 封装排序参数 20 | */ 21 | public class ESSort { 22 | 23 | public final List orders; 24 | public ESSort() { 25 | orders = new ArrayList<>(); 26 | } 27 | 28 | public ESSort(SortOrder direction, String property) { 29 | orders = new ArrayList<>(); 30 | add(direction,property); 31 | } 32 | 33 | 34 | 35 | /** 36 | * 追加排序字段 37 | * @param direction 排序方向 38 | * @param property 排序字段 39 | * @return 40 | */ 41 | public ESSort add(SortOrder direction, String property) { 42 | 43 | Assert.notNull(direction, "direction must not be null!"); 44 | Assert.hasText(property, "fieldName must not be empty!"); 45 | 46 | orders.add(ESOrder.builder().direction(direction).property(property).build()); 47 | return this; 48 | } 49 | 50 | 51 | @Builder 52 | @Data 53 | public static class ESOrder implements Serializable { 54 | 55 | private final SortOrder direction; 56 | private final String property; 57 | 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/model/GoodsESEntity.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.model; 2 | 3 | import com.zbq.springbootelasticsearch.common.elasticsearch.annotation.ESDocument; 4 | import com.zbq.springbootelasticsearch.common.elasticsearch.annotation.ESField; 5 | import com.zbq.springbootelasticsearch.common.elasticsearch.annotation.ESId; 6 | import com.zbq.springbootelasticsearch.common.elasticsearch.enums.ESFieldType; 7 | import lombok.AllArgsConstructor; 8 | import lombok.Builder; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | 12 | /** 13 | * @author zhangboqing 14 | * @date 2019/12/10 15 | */ 16 | @Data 17 | @NoArgsConstructor 18 | @AllArgsConstructor 19 | @Builder 20 | @ESDocument(indexName = "goods") 21 | public class GoodsESEntity { 22 | // 筛选条件包括:商品名称,品牌,规格,适用车型,商品编号,原厂编号 23 | 24 | /** 25 | * 主键,商品ID 26 | */ 27 | @ESId 28 | @ESField(value = "goodsId",type = ESFieldType.Long) 29 | private Long goodsId; 30 | 31 | /** 32 | * 商品名称 33 | */ 34 | @ESField(value = "goodsName",type = ESFieldType.Keyword) 35 | private String goodsName; 36 | /** 37 | * 品牌 38 | */ 39 | @ESField(value = "goodBrand",type = ESFieldType.Keyword) 40 | private String goodBrand; 41 | /** 42 | * 规格 43 | */ 44 | @ESField(value = "goodsSpec",type = ESFieldType.Keyword) 45 | private String goodsSpec; 46 | /** 47 | * 商品编号 48 | */ 49 | @ESField(value = "goodsAccessoriesCode",type = ESFieldType.Keyword) 50 | private String goodsAccessoriesCode; 51 | /** 52 | * 原厂编号 53 | */ 54 | @ESField(value = "goodsOriginalFactoryCode",type = ESFieldType.Keyword) 55 | private String goodsOriginalFactoryCode; 56 | 57 | /** 58 | * 复合字段,会被分词后存储 59 | */ 60 | @ESField(value = "groupData",type = ESFieldType.Text,analyzer = "ik_smart") 61 | private String groupData; 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/com/zbq/springbootelasticsearch/ElasticSearchTest.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.zbq.springbootelasticsearch.common.enums.ElasticsearchIndexEnum; 5 | import com.zbq.springbootelasticsearch.model.GoodsESEntity; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.elasticsearch.action.bulk.BulkRequest; 8 | import org.elasticsearch.action.bulk.BulkResponse; 9 | import org.elasticsearch.action.index.IndexRequest; 10 | import org.elasticsearch.client.RequestOptions; 11 | import org.elasticsearch.client.RestHighLevelClient; 12 | import org.elasticsearch.common.xcontent.XContentType; 13 | import org.junit.jupiter.api.Test; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.beans.factory.annotation.Qualifier; 16 | import org.springframework.boot.test.context.SpringBootTest; 17 | import org.springframework.test.context.junit4.SpringRunner; 18 | import org.springframework.test.context.web.WebAppConfiguration; 19 | 20 | import java.io.IOException; 21 | 22 | /** 23 | * @author zhangboqing 24 | * @date 2018/10/23 25 | */ 26 | @SpringBootTest 27 | @Slf4j 28 | public class ElasticSearchTest { 29 | 30 | @Autowired 31 | private RestHighLevelClient restHighLevelClient; 32 | 33 | /** 34 | * 测试新增 35 | */ 36 | @Test 37 | public void insertTest() throws IOException { 38 | GoodsESEntity goodsESEntity = GoodsESEntity.builder().goodsId(1L).goodsName("1").goodBrand("1").goodsSpec("1").goodsAccessoriesCode("1").goodsOriginalFactoryCode("1").build(); 39 | BulkRequest request = new BulkRequest(); 40 | request.add(new IndexRequest(ElasticsearchIndexEnum.GOODS.getIndexName()).id("1").source(JSON.toJSONString(goodsESEntity),XContentType.JSON)); 41 | BulkResponse bulk = restHighLevelClient.bulk(request, RequestOptions.DEFAULT); 42 | log.info("==========================> {}",JSON.toJSONString(bulk)); 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/config/ElasticsearchProperties.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.common.config; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import org.springframework.boot.context.properties.ConfigurationProperties; 8 | import org.springframework.stereotype.Component; 9 | 10 | import javax.validation.constraints.NotNull; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | 15 | /** 16 | * @author zhangboqing 17 | * @date 2019/12/10 18 | */ 19 | @Data 20 | @Builder 21 | @Component 22 | @NoArgsConstructor 23 | @AllArgsConstructor 24 | @ConfigurationProperties(prefix = "demo.data.elasticsearch") 25 | public class ElasticsearchProperties { 26 | 27 | /** 28 | * 请求协议 29 | */ 30 | private String schema = "http"; 31 | 32 | /** 33 | * 集群名称 34 | */ 35 | private String clusterName = "elasticsearch"; 36 | 37 | /** 38 | * 集群节点 39 | */ 40 | @NotNull(message = "集群节点不允许为空") 41 | private List clusterNodes = new ArrayList<>(); 42 | 43 | /** 44 | * 连接超时时间(毫秒) 45 | */ 46 | private Integer connectTimeout = 1000; 47 | 48 | /** 49 | * socket 超时时间 50 | */ 51 | private Integer socketTimeout = 30000; 52 | 53 | /** 54 | * 连接请求超时时间 55 | */ 56 | private Integer connectionRequestTimeout = 500; 57 | 58 | /** 59 | * 每个路由的最大连接数量 60 | */ 61 | private Integer maxConnectPerRoute = 10; 62 | 63 | /** 64 | * 最大连接总数量 65 | */ 66 | private Integer maxConnectTotal = 30; 67 | 68 | /** 69 | * 索引配置信息 70 | */ 71 | private Index index = new Index(); 72 | 73 | /** 74 | * 认证账户 75 | */ 76 | private Account account = new Account(); 77 | 78 | /** 79 | * 索引配置信息 80 | */ 81 | @Data 82 | public static class Index { 83 | 84 | /** 85 | * 分片数量 86 | */ 87 | private Integer numberOfShards = 3; 88 | 89 | /** 90 | * 副本数量 91 | */ 92 | private Integer numberOfReplicas = 2; 93 | 94 | } 95 | 96 | /** 97 | * 认证账户 98 | */ 99 | @Data 100 | public static class Account { 101 | 102 | /** 103 | * 认证用户 104 | */ 105 | private String username; 106 | 107 | /** 108 | * 认证密码 109 | */ 110 | private String password; 111 | 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/test/java/com/zbq/springbootelasticsearch/GoodsESDaoTest.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch; 2 | 3 | import com.zbq.springbootelasticsearch.common.elasticsearch.base.ESPageResult; 4 | import com.zbq.springbootelasticsearch.dao.GoodsESDao; 5 | import com.zbq.springbootelasticsearch.model.GoodsESEntity; 6 | import org.junit.jupiter.api.Test; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | @SpringBootTest 14 | class GoodsESDaoTest { 15 | 16 | @Autowired 17 | private GoodsESDao goodsESDao; 18 | 19 | 20 | /** 21 | * 测试新增或更新 22 | */ 23 | @Test 24 | public void saveOrUpdateTest() { 25 | List list = new ArrayList<>(); 26 | list.add(GoodsESEntity.builder().goodsId(1L).goodsName("保时捷跑车V10").goodBrand("国际1").goodsSpec("哈哈1").goodsAccessoriesCode("所噶1").goodsOriginalFactoryCode("2121").groupData("保时捷跑车V10 国际1 哈哈1 所噶1 2121").build()); 27 | list.add(GoodsESEntity.builder().goodsId(2L).goodsName("保时捷跑车V10").goodBrand("国际2").goodsSpec("哈哈2").goodsAccessoriesCode("所噶2").goodsOriginalFactoryCode("2122").groupData("保时捷跑车V20 国际2 哈哈2 所噶2 2122").build()); 28 | list.add(GoodsESEntity.builder().goodsId(3L).goodsName("保时捷跑车V20").goodBrand("国际1").goodsSpec("哈哈3").goodsAccessoriesCode("所噶3").goodsOriginalFactoryCode("2123").groupData("保时捷跑车V30 国际3 哈哈3 所噶3 2123").build()); 29 | list.add(GoodsESEntity.builder().goodsId(4L).goodsName("保时捷跑车V20").goodBrand("国际2").goodsSpec("哈哈4").goodsAccessoriesCode("所噶4").goodsOriginalFactoryCode("2124").groupData("保时捷跑车V40 国际4 哈哈4 所噶4 2124").build()); 30 | list.add(GoodsESEntity.builder().goodsId(5L).goodsName("保时捷跑车V30").goodBrand("国际1").goodsSpec("哈哈5").goodsAccessoriesCode("所噶5").goodsOriginalFactoryCode("2125").groupData("保时捷跑车V50 国际5 哈哈5 所噶5 2125").build()); 31 | list.add(GoodsESEntity.builder().goodsId(6L).goodsName("保时捷跑车V40").goodBrand("国际2").goodsSpec("哈哈6").goodsAccessoriesCode("所噶6").goodsOriginalFactoryCode("2126").groupData("保时捷跑车V60 国际6 哈哈6 所噶6 2126").build()); 32 | 33 | goodsESDao.saveOrUpdate(list); 34 | } 35 | 36 | /** 37 | * 测试删除 38 | */ 39 | @Test 40 | public void deleteTest() { 41 | goodsESDao.delete(GoodsESEntity.builder().goodsId(2L).build()); 42 | } 43 | 44 | /** 45 | * 测试分词查询 46 | */ 47 | @Test 48 | public void searchListByAnalysisTest() { 49 | List goodsESEntityList = goodsESDao.findListByAnalysisForGroupData("所"); 50 | System.out.println(goodsESEntityList); 51 | } 52 | 53 | /** 54 | * 测试等值查询 55 | */ 56 | @Test 57 | public void searchListByEqTest() { 58 | List goodsESEntityList = goodsESDao.findListByEq(); 59 | System.out.println(goodsESEntityList); 60 | } 61 | 62 | /** 63 | * 测试like查询 64 | */ 65 | @Test 66 | public void searchListByLikeTest() { 67 | List goodsESEntityList = goodsESDao.findListByLike(); 68 | System.out.println(goodsESEntityList); 69 | } 70 | 71 | /** 72 | * 测试分页和排序 73 | */ 74 | @Test 75 | public void findList() { 76 | 77 | ESPageResult esPageResult = goodsESDao.findList("所"); 78 | System.out.println(esPageResult); 79 | 80 | } 81 | } -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/dao/GoodsESDao.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.dao; 2 | 3 | import com.zbq.springbootelasticsearch.common.elasticsearch.base.BaseElasticsearchDao; 4 | import com.zbq.springbootelasticsearch.common.elasticsearch.base.ESPageRequest; 5 | import com.zbq.springbootelasticsearch.common.elasticsearch.base.ESPageResult; 6 | import com.zbq.springbootelasticsearch.common.elasticsearch.base.ESSort; 7 | import com.zbq.springbootelasticsearch.model.GoodsESEntity; 8 | import org.elasticsearch.index.query.BoolQueryBuilder; 9 | import org.elasticsearch.index.query.QueryBuilders; 10 | import org.elasticsearch.search.builder.SearchSourceBuilder; 11 | import org.elasticsearch.search.sort.SortOrder; 12 | import org.springframework.stereotype.Component; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * @author zhangboqing 18 | * @date 2019/12/10 19 | */ 20 | @Component 21 | public class GoodsESDao extends BaseElasticsearchDao { 22 | 23 | 24 | /** 25 | * 全文搜索查询 26 | * @param queryName 27 | * @return 28 | */ 29 | public List findListByAnalysisForGroupData(String queryName) { 30 | SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 31 | searchSourceBuilder.query(QueryBuilders.matchQuery("groupData",queryName)); 32 | List search = search(searchSourceBuilder); 33 | return search; 34 | } 35 | 36 | /** 37 | * 多条件等值查询查询 38 | * @return 39 | */ 40 | public List findListByEq() { 41 | SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 42 | BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); 43 | boolQueryBuilder.filter(QueryBuilders.matchQuery("goodsName","保时捷跑车V10")); 44 | boolQueryBuilder.filter(QueryBuilders.matchQuery("goodBrand","国际1")); 45 | searchSourceBuilder.query(boolQueryBuilder); 46 | List search = search(searchSourceBuilder); 47 | return search; 48 | } 49 | 50 | /** 51 | * 多条件like查询查询 52 | * @return 53 | */ 54 | public List findListByLike() { 55 | SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 56 | BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); 57 | boolQueryBuilder.filter(QueryBuilders.wildcardQuery("goodsName","?V10")); 58 | boolQueryBuilder.filter(QueryBuilders.wildcardQuery("goodBrand","国际1")); 59 | searchSourceBuilder.query(boolQueryBuilder); 60 | List search = search(searchSourceBuilder); 61 | return search; 62 | } 63 | 64 | /** 65 | * 全文搜索查询分页排序 66 | * @param queryName 67 | * @return 68 | * QueryBuilders.boolQuery() 69 | */ 70 | public ESPageResult findList(String queryName) { 71 | // 搜索条件 72 | SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 73 | searchSourceBuilder.query(QueryBuilders.matchQuery("groupData",queryName)); 74 | 75 | // 分页 76 | ESPageRequest esPageRequest = new ESPageRequest(1, 2); 77 | 78 | // 排序 79 | ESSort esSort = new ESSort(SortOrder.ASC,"goodsName"); 80 | 81 | ESPageResult search = search(searchSourceBuilder, esPageRequest, esSort); 82 | return search; 83 | } 84 | } 85 | 86 | 87 | -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/config/ElasticsearchApplicationListener.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.common.config; 2 | 3 | import com.zbq.springbootelasticsearch.common.elasticsearch.annotation.ESDocument; 4 | import com.zbq.springbootelasticsearch.common.exception.ElasticsearchException; 5 | import com.zbq.springbootelasticsearch.common.elasticsearch.base.BaseElasticsearchDao; 6 | import com.zbq.springbootelasticsearch.common.elasticsearch.base.ElasticsearchUtils; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.beans.BeansException; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.context.ApplicationContext; 11 | import org.springframework.context.ApplicationContextAware; 12 | import org.springframework.context.ApplicationListener; 13 | import org.springframework.context.event.ContextRefreshedEvent; 14 | import org.springframework.core.GenericTypeResolver; 15 | import org.springframework.core.annotation.AnnotationUtils; 16 | import org.springframework.stereotype.Component; 17 | import org.springframework.util.StringUtils; 18 | 19 | /** 20 | * @author zhangboqing 21 | * @date 2019/12/10 22 | */ 23 | @Component 24 | @Slf4j 25 | public class ElasticsearchApplicationListener implements ApplicationListener, ApplicationContextAware { 26 | 27 | @Autowired 28 | protected ElasticsearchUtils elasticsearchUtils; 29 | 30 | private ApplicationContext applicationContext; 31 | 32 | @Override 33 | public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) { 34 | 35 | String[] beanNames = applicationContext.getBeanNamesForType(BaseElasticsearchDao.class); 36 | if (beanNames != null && beanNames.length > 0) { 37 | for (int i = 0; i < beanNames.length; i++) { 38 | String beanName = beanNames[i]; 39 | if (beanName.contains("com.zbq.springbootelasticsearch.common.elasticsearch.base.BaseElasticsearchDao")) { 40 | continue; 41 | } 42 | Object bean = applicationContext.getBean(beanName); 43 | Class targetBeanClass = bean.getClass(); 44 | Class beanClass = GenericTypeResolver.resolveTypeArgument(targetBeanClass, BaseElasticsearchDao.class); 45 | ESDocument esDocument = AnnotationUtils.findAnnotation(beanClass, ESDocument.class); 46 | if (esDocument == null) { 47 | throw new ElasticsearchException("ESDocument注解未指定"); 48 | } 49 | String indexName = esDocument.indexName(); 50 | if (StringUtils.isEmpty(indexName)) { 51 | throw new ElasticsearchException("indexName未指定"); 52 | } 53 | int shards = esDocument.shards(); 54 | int replicas = esDocument.replicas(); 55 | 56 | if (shards == 0 || replicas == 0) { 57 | elasticsearchUtils.createIndexRequest(indexName); 58 | } else { 59 | elasticsearchUtils.createIndexRequest(indexName, shards, replicas); 60 | } 61 | elasticsearchUtils.putMappingRequest(indexName, beanClass); 62 | } 63 | } 64 | 65 | } 66 | 67 | @Override 68 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 69 | this.applicationContext = applicationContext; 70 | } 71 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.2.2.RELEASE 9 | 10 | 11 | com.zbq 12 | spring-boot-demo-elasticsearch-rest-high-level-client 13 | 0.0.1-SNAPSHOT 14 | spring-boot-demo-elasticsearch-rest-high-level-client 15 | Demo project for Spring Boot 16 | 17 | 18 | 1.8 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter 25 | 26 | 27 | 28 | org.elasticsearch.client 29 | elasticsearch-rest-high-level-client 30 | 7.4.2 31 | 32 | 33 | elasticsearch 34 | org.elasticsearch 35 | 36 | 37 | elasticsearch-rest-client 38 | org.elasticsearch.client 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.elasticsearch 50 | elasticsearch 51 | 7.4.2 52 | compile 53 | 54 | 55 | org.elasticsearch.client 56 | elasticsearch-rest-client 57 | 7.4.2 58 | compile 59 | 60 | 61 | 62 | com.alibaba 63 | fastjson 64 | 1.2.58 65 | 66 | 67 | org.projectlombok 68 | lombok 69 | true 70 | 71 | 72 | org.springframework.boot 73 | spring-boot-starter-validation 74 | 75 | 76 | org.springframework.boot 77 | spring-boot-starter-test 78 | test 79 | 80 | 81 | org.junit.vintage 82 | junit-vintage-engine 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | org.springframework.boot 92 | spring-boot-maven-plugin 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/config/ElasticsearchConfig.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.common.config; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import org.apache.http.HttpHost; 5 | import org.apache.http.auth.AuthScope; 6 | import org.apache.http.auth.UsernamePasswordCredentials; 7 | import org.apache.http.client.CredentialsProvider; 8 | import org.apache.http.client.config.RequestConfig; 9 | import org.apache.http.impl.client.BasicCredentialsProvider; 10 | import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; 11 | import org.elasticsearch.client.RestClient; 12 | import org.elasticsearch.client.RestClientBuilder; 13 | import org.elasticsearch.client.RestHighLevelClient; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 16 | import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration; 17 | import org.springframework.boot.autoconfigure.elasticsearch.rest.RestClientAutoConfiguration; 18 | import org.springframework.context.annotation.Bean; 19 | import org.springframework.context.annotation.Configuration; 20 | import org.springframework.util.Assert; 21 | import org.springframework.util.StringUtils; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | 26 | 27 | /** 28 | * @author zhangboqing 29 | * @date 2019/12/10 30 | */ 31 | @Configuration 32 | @RequiredArgsConstructor(onConstructor_ = @Autowired) 33 | @EnableAutoConfiguration(exclude = {RestClientAutoConfiguration.class}) 34 | public class ElasticsearchConfig { 35 | 36 | private final ElasticsearchProperties elasticsearchProperties; 37 | 38 | @Bean 39 | public RestHighLevelClient initailizationRestHighLevelClient() { 40 | 41 | // 设置es节点 42 | List httpHosts = new ArrayList<>(); 43 | List clusterNodes = elasticsearchProperties.getClusterNodes(); 44 | clusterNodes.forEach(node -> { 45 | try { 46 | String[] parts = StringUtils.split(node, ":"); 47 | Assert.notNull(parts, "Must defined"); 48 | Assert.state(parts.length == 2, "Must be defined as 'host:port'"); 49 | httpHosts.add(new HttpHost(parts[0], Integer.parseInt(parts[1]), elasticsearchProperties.getSchema())); 50 | } catch (Exception e) { 51 | throw new IllegalStateException("Invalid ES nodes " + "property '" + node + "'", e); 52 | } 53 | }); 54 | RestClientBuilder builder = RestClient.builder(httpHosts.toArray(new HttpHost[0])); 55 | 56 | final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); 57 | credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("elastic", "123456")); 58 | builder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() { 59 | @Override 60 | public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) { 61 | return httpClientBuilder 62 | // 线程数量 63 | // .setDefaultIOReactorConfig( 64 | // IOReactorConfig.custom() 65 | // .setIoThreadCount(1) 66 | // .build()) 67 | // 认证设置 68 | .setDefaultCredentialsProvider(credentialsProvider); 69 | } 70 | }) 71 | // 超时时间 72 | .setRequestConfigCallback( 73 | new RestClientBuilder.RequestConfigCallback() { 74 | @Override 75 | public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) { 76 | return requestConfigBuilder.setConnectTimeout(5000).setSocketTimeout(60000); 77 | } 78 | }); 79 | 80 | 81 | RestHighLevelClient client = new RestHighLevelClient(builder); 82 | return client; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/exception/ApiException.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.common.exception; 2 | 3 | public class ApiException extends RuntimeException { 4 | private ApiResponseCode responseCode; 5 | private IApiResponseCode iApiResponseCode; 6 | private ApiException.ErrorPrintLogLevelEnum errorPrintLogLevelEnum; 7 | private Integer code; 8 | 9 | public ApiException() { 10 | } 11 | 12 | public ApiException(String message) { 13 | super(message); 14 | } 15 | 16 | public ApiException(String message, Throwable cause) { 17 | super(message, cause); 18 | } 19 | 20 | public ApiException(Throwable cause) { 21 | super(cause); 22 | } 23 | 24 | public ApiException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 25 | super(message, cause, enableSuppression, writableStackTrace); 26 | } 27 | 28 | public ApiException(Integer code, String message) { 29 | super(message); 30 | this.code = code; 31 | } 32 | 33 | public ApiException(ApiResponseCode responseCode) { 34 | super(responseCode.message); 35 | this.responseCode = responseCode; 36 | this.code = responseCode.getCode(); 37 | } 38 | 39 | public ApiException(ApiResponseCode responseCode, String message) { 40 | super(message); 41 | this.responseCode = responseCode; 42 | this.code = responseCode.getCode(); 43 | } 44 | 45 | public ApiException(ApiResponseCode responseCode, Throwable cause) { 46 | super(responseCode.message, cause); 47 | this.responseCode = responseCode; 48 | this.code = responseCode.getCode(); 49 | } 50 | 51 | public ApiException(ApiResponseCode responseCode, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 52 | super(responseCode.message, cause, enableSuppression, writableStackTrace); 53 | this.responseCode = responseCode; 54 | this.code = responseCode.getCode(); 55 | } 56 | 57 | public ApiException(IApiResponseCode iApiResponseCode) { 58 | super(iApiResponseCode.getMessage()); 59 | this.iApiResponseCode = iApiResponseCode; 60 | this.code = iApiResponseCode.getCode(); 61 | } 62 | 63 | public ApiException(IApiResponseCode iApiResponseCode, String message) { 64 | super(message); 65 | this.iApiResponseCode = iApiResponseCode; 66 | this.code = iApiResponseCode.getCode(); 67 | } 68 | 69 | public ApiException(IApiResponseCode iApiResponseCode, String message, ApiException.ErrorPrintLogLevelEnum errorPrintLogLevel) { 70 | super(message); 71 | this.iApiResponseCode = iApiResponseCode; 72 | this.code = iApiResponseCode.getCode(); 73 | this.errorPrintLogLevelEnum = errorPrintLogLevel; 74 | } 75 | 76 | public ApiException(IApiResponseCode iApiResponseCode, Throwable cause) { 77 | super(iApiResponseCode.getMessage(), cause); 78 | this.iApiResponseCode = iApiResponseCode; 79 | this.code = iApiResponseCode.getCode(); 80 | } 81 | 82 | public ApiException(IApiResponseCode iApiResponseCode, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 83 | super(iApiResponseCode.getMessage(), cause, enableSuppression, writableStackTrace); 84 | this.iApiResponseCode = iApiResponseCode; 85 | this.code = iApiResponseCode.getCode(); 86 | } 87 | 88 | public ApiResponseCode getResponseCode() { 89 | return this.responseCode; 90 | } 91 | 92 | public IApiResponseCode getIApiResponseCode() { 93 | return this.iApiResponseCode; 94 | } 95 | 96 | public ApiException.ErrorPrintLogLevelEnum getErrorPrintLogLevelEnum() { 97 | return this.errorPrintLogLevelEnum; 98 | } 99 | 100 | public Integer getCode() { 101 | return this.code; 102 | } 103 | 104 | public void setResponseCode(ApiResponseCode responseCode) { 105 | this.responseCode = responseCode; 106 | } 107 | 108 | public void setIApiResponseCode(IApiResponseCode iApiResponseCode) { 109 | this.iApiResponseCode = iApiResponseCode; 110 | } 111 | 112 | public void setErrorPrintLogLevelEnum(ApiException.ErrorPrintLogLevelEnum errorPrintLogLevelEnum) { 113 | this.errorPrintLogLevelEnum = errorPrintLogLevelEnum; 114 | } 115 | 116 | public void setCode(Integer code) { 117 | this.code = code; 118 | } 119 | 120 | public static enum ErrorPrintLogLevelEnum { 121 | NONE, 122 | TRACE, 123 | DEBUG, 124 | INFO, 125 | WARN, 126 | ERROR; 127 | 128 | private ErrorPrintLogLevelEnum() { 129 | } 130 | } 131 | } -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/elasticsearch/base/BaseElasticsearchDao.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.common.elasticsearch.base; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.zbq.springbootelasticsearch.common.elasticsearch.annotation.ESDocument; 5 | import com.zbq.springbootelasticsearch.common.elasticsearch.annotation.ESId; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.apache.lucene.search.TotalHits; 8 | import org.elasticsearch.action.index.IndexRequest; 9 | import org.elasticsearch.action.search.SearchRequest; 10 | import org.elasticsearch.action.search.SearchResponse; 11 | import org.elasticsearch.client.RequestOptions; 12 | import org.elasticsearch.client.RestHighLevelClient; 13 | import org.elasticsearch.search.SearchHit; 14 | import org.elasticsearch.search.SearchHits; 15 | import org.elasticsearch.search.builder.SearchSourceBuilder; 16 | import org.elasticsearch.search.sort.SortOrder; 17 | import org.springframework.beans.factory.annotation.Autowired; 18 | import org.springframework.core.GenericTypeResolver; 19 | import org.springframework.core.annotation.AnnotationUtils; 20 | import org.springframework.util.Assert; 21 | import org.springframework.util.CollectionUtils; 22 | import org.springframework.util.ObjectUtils; 23 | 24 | import java.io.IOException; 25 | import java.lang.reflect.Field; 26 | import java.util.ArrayList; 27 | import java.util.Arrays; 28 | import java.util.List; 29 | 30 | /** 31 | * @author zhangboqing 32 | * @date 2019/12/10 33 | */ 34 | @Slf4j 35 | public abstract class BaseElasticsearchDao { 36 | 37 | @Autowired 38 | protected ElasticsearchUtils elasticsearchUtils; 39 | @Autowired 40 | protected RestHighLevelClient client; 41 | 42 | /** 43 | * 索引名称 44 | */ 45 | protected String indexName; 46 | /** 47 | * ID字段 48 | */ 49 | protected Field idField; 50 | /** 51 | * T对应的类型Class 52 | */ 53 | protected Class genericClass; 54 | 55 | public BaseElasticsearchDao() { 56 | Class beanClass = (Class) GenericTypeResolver.resolveTypeArgument(this.getClass(), BaseElasticsearchDao.class); 57 | this.genericClass = beanClass; 58 | 59 | ESDocument esDocument = AnnotationUtils.findAnnotation(beanClass, ESDocument.class); 60 | this.indexName = esDocument.indexName(); 61 | 62 | Field[] declaredFields = beanClass.getDeclaredFields(); 63 | for (Field declaredField : declaredFields) { 64 | ESId esId = declaredField.getAnnotation(ESId.class); 65 | if (esId != null) { 66 | this.idField = declaredField; 67 | idField.setAccessible(true); 68 | break; 69 | } 70 | } 71 | } 72 | 73 | 74 | /** 75 | * 保存或更新文档数据 76 | * 77 | * @param list 文档数据集合 78 | */ 79 | public void saveOrUpdate(List list) { 80 | 81 | list.forEach(genericInstance -> { 82 | IndexRequest request = ElasticsearchUtils.buildIndexRequest(indexName, getIdValue(genericInstance), genericInstance); 83 | try { 84 | client.index(request, RequestOptions.DEFAULT); 85 | } catch (IOException e) { 86 | e.printStackTrace(); 87 | log.error("elasticsearch insert error", e); 88 | } 89 | }); 90 | 91 | } 92 | 93 | /** 94 | * 删除操作 95 | * 当genericInstance在es中不存在时,调用该方法也不会报错 96 | * 97 | * @param genericInstance 被删除的实例对象 98 | */ 99 | public void delete(T genericInstance) { 100 | if (ObjectUtils.isEmpty(genericInstance)) { 101 | // 如果对象为空,则删除全量 102 | searchList().forEach(result -> { 103 | 104 | elasticsearchUtils.deleteRequest(indexName, getIdValue(genericInstance)); 105 | }); 106 | } 107 | elasticsearchUtils.deleteRequest(indexName, getIdValue(genericInstance)); 108 | } 109 | 110 | /** 111 | * 搜索文档,根据指定的搜索条件 112 | * 113 | * @param searchSourceBuilder 114 | * @return 115 | */ 116 | public List search(SearchSourceBuilder searchSourceBuilder) { 117 | ESSort esSort = new ESSort(SortOrder.ASC,"goodsName"); 118 | ESPageResult search = search(searchSourceBuilder, null, null); 119 | return search != null ? search.getResults() : null; 120 | 121 | } 122 | 123 | /** 124 | * 分页排序搜索文档,根据指定的搜索条件 125 | * 126 | * @param searchSourceBuilder 127 | * @param esPageRequest 分页 128 | * @param esSort 排序 129 | * @return 130 | */ 131 | public ESPageResult search(SearchSourceBuilder searchSourceBuilder, ESPageRequest esPageRequest, ESSort esSort) { 132 | 133 | // 搜索 134 | Assert.notNull(searchSourceBuilder, "searchSourceBuilder is null"); 135 | SearchRequest searchRequest = new SearchRequest(indexName); 136 | searchRequest.source(searchSourceBuilder); 137 | 138 | // 分页 139 | if (esPageRequest != null) { 140 | searchSourceBuilder.from(esPageRequest.getPageNo()); 141 | searchSourceBuilder.size(esPageRequest.getSize()); 142 | } 143 | 144 | // 排序 145 | if (esSort != null) { 146 | List orders = esSort.orders; 147 | if (!CollectionUtils.isEmpty(orders)) { 148 | orders.forEach(esOrder -> searchSourceBuilder.sort(esOrder.getProperty(), esOrder.getDirection())); 149 | } 150 | } 151 | 152 | SearchResponse searchResponse = null; 153 | try { 154 | searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); 155 | } catch (IOException e) { 156 | e.printStackTrace(); 157 | } 158 | if (searchResponse == null) { 159 | return null; 160 | } 161 | 162 | SearchHits searchHits = searchResponse.getHits(); 163 | SearchHit[] hits = searchHits.getHits(); 164 | List genericInstanceList = new ArrayList<>(); 165 | Arrays.stream(hits).forEach(hit -> { 166 | String sourceAsString = hit.getSourceAsString(); 167 | genericInstanceList.add(JSON.parseObject(sourceAsString, genericClass)); 168 | }); 169 | 170 | TotalHits totalHits = searchHits.getTotalHits(); 171 | long total = totalHits.value; 172 | ESPageResult pageResult = new ESPageResult<>( 173 | total, 174 | esPageRequest != null ? esPageRequest.getPageNo() : -1, 175 | esPageRequest != null ? esPageRequest.getSize() : -1, 176 | genericInstanceList); 177 | return pageResult; 178 | 179 | } 180 | 181 | 182 | 183 | 184 | /** 185 | * ============================================================================================================ 186 | * 私有方法 187 | * ============================================================================================================ 188 | * */ 189 | 190 | private List searchList() { 191 | SearchResponse searchResponse = elasticsearchUtils.search(indexName); 192 | SearchHit[] hits = searchResponse.getHits().getHits(); 193 | List genericInstanceList = new ArrayList<>(); 194 | Arrays.stream(hits).forEach(hit -> { 195 | String sourceAsString = hit.getSourceAsString(); 196 | genericInstanceList.add(JSON.parseObject(sourceAsString, genericClass)); 197 | }); 198 | return genericInstanceList; 199 | } 200 | 201 | /** 202 | * 获取当前操作的genericInstance的主键ID 203 | * 204 | * @param genericInstance 实例对象 205 | * @return 返回主键ID值 206 | */ 207 | private String getIdValue(T genericInstance) { 208 | try { 209 | Object idValue = idField.get(genericInstance); 210 | return idValue.toString(); 211 | } catch (IllegalAccessException e) { 212 | e.printStackTrace(); 213 | } 214 | 215 | return null; 216 | } 217 | 218 | } 219 | -------------------------------------------------------------------------------- /src/main/java/com/zbq/springbootelasticsearch/common/elasticsearch/base/ElasticsearchUtils.java: -------------------------------------------------------------------------------- 1 | package com.zbq.springbootelasticsearch.common.elasticsearch.base; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.zbq.springbootelasticsearch.common.config.ElasticsearchProperties; 5 | import com.zbq.springbootelasticsearch.common.elasticsearch.annotation.ESField; 6 | import com.zbq.springbootelasticsearch.common.elasticsearch.annotation.ESId; 7 | import com.zbq.springbootelasticsearch.common.elasticsearch.enums.ESFieldType; 8 | import com.zbq.springbootelasticsearch.common.exception.ElasticsearchException; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; 11 | import org.elasticsearch.action.delete.DeleteRequest; 12 | import org.elasticsearch.action.index.IndexRequest; 13 | import org.elasticsearch.action.search.SearchRequest; 14 | import org.elasticsearch.action.search.SearchResponse; 15 | import org.elasticsearch.action.support.master.AcknowledgedResponse; 16 | import org.elasticsearch.action.update.UpdateRequest; 17 | import org.elasticsearch.client.HttpAsyncResponseConsumerFactory; 18 | import org.elasticsearch.client.RequestOptions; 19 | import org.elasticsearch.client.RestHighLevelClient; 20 | import org.elasticsearch.client.indices.CreateIndexRequest; 21 | import org.elasticsearch.client.indices.CreateIndexResponse; 22 | import org.elasticsearch.client.indices.GetIndexRequest; 23 | import org.elasticsearch.client.indices.PutMappingRequest; 24 | import org.elasticsearch.common.settings.Settings; 25 | import org.elasticsearch.common.xcontent.XContentBuilder; 26 | import org.elasticsearch.common.xcontent.XContentFactory; 27 | import org.elasticsearch.common.xcontent.XContentType; 28 | import org.elasticsearch.index.query.QueryBuilders; 29 | import org.elasticsearch.search.builder.SearchSourceBuilder; 30 | import org.springframework.beans.factory.annotation.Autowired; 31 | import org.springframework.core.annotation.AnnotatedElementUtils; 32 | import org.springframework.core.annotation.AnnotationAttributes; 33 | import org.springframework.stereotype.Component; 34 | import org.springframework.util.StringUtils; 35 | 36 | import java.io.IOException; 37 | import java.lang.reflect.Field; 38 | 39 | /** 40 | * @author zhangboqing 41 | * @date 2019/12/10 42 | */ 43 | @Slf4j 44 | @Component 45 | public class ElasticsearchUtils { 46 | 47 | @Autowired 48 | public RestHighLevelClient client; 49 | 50 | @Autowired 51 | private ElasticsearchProperties elasticsearchProperties; 52 | 53 | public static final RequestOptions COMMON_OPTIONS; 54 | 55 | static { 56 | RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); 57 | 58 | // 默认缓冲限制为100MB,此处修改为30MB。 59 | builder.setHttpAsyncResponseConsumerFactory(new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(30 * 1024 * 1024)); 60 | COMMON_OPTIONS = builder.build(); 61 | } 62 | 63 | 64 | public boolean existIndex(String indexName) { 65 | boolean exists = false; 66 | try { 67 | GetIndexRequest request = new GetIndexRequest(indexName); 68 | exists = client.indices().exists(request, RequestOptions.DEFAULT); 69 | } catch (IOException e) { 70 | e.printStackTrace(); 71 | throw new ElasticsearchException("判断索引 {" + indexName + "} 是否存在失败"); 72 | } 73 | return exists; 74 | } 75 | 76 | public void createIndexRequest(String indexName) { 77 | createIndexRequest(indexName, elasticsearchProperties.getIndex().getNumberOfShards(), elasticsearchProperties.getIndex().getNumberOfReplicas()); 78 | } 79 | 80 | public void createIndexRequest(String indexName, int shards, int replicas) { 81 | if (existIndex(indexName)) { 82 | return; 83 | } 84 | 85 | try { 86 | CreateIndexRequest request = new CreateIndexRequest(indexName); 87 | // Settings for this index 88 | request.settings(Settings.builder() 89 | .put("index.number_of_shards", shards) 90 | .put("index.number_of_replicas", replicas) 91 | ); 92 | 93 | CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT); 94 | log.info(" acknowledged : {}", createIndexResponse.isAcknowledged()); 95 | log.info(" shardsAcknowledged :{}", createIndexResponse.isShardsAcknowledged()); 96 | } catch (IOException e) { 97 | throw new ElasticsearchException("创建索引 {" + indexName + "} 失败"); 98 | } 99 | } 100 | 101 | public void putMappingRequest(String indexName, Class clazz) { 102 | Field[] fields = clazz.getDeclaredFields(); 103 | if (fields == null || fields.length == 0) { 104 | return; 105 | } 106 | 107 | try { 108 | PutMappingRequest request = new PutMappingRequest(indexName); 109 | XContentBuilder builder = XContentFactory.jsonBuilder(); 110 | builder.startObject(); 111 | { 112 | builder.startObject("properties"); 113 | { 114 | for (int i = 0; i < fields.length; i++) { 115 | Field field = fields[i]; 116 | ESId esId = field.getAnnotation(ESId.class); 117 | if (esId != null) { 118 | continue; 119 | } else { 120 | AnnotationAttributes esField = AnnotatedElementUtils.getMergedAnnotationAttributes(field, ESField.class); 121 | if (esField == null) { 122 | continue; 123 | } 124 | String name = esField.getString("name"); 125 | if (StringUtils.isEmpty(name)) { 126 | throw new ElasticsearchException("注解ESField的name属性未指定"); 127 | } 128 | ESFieldType esFieldType = (ESFieldType) esField.get("type"); 129 | if (esFieldType == null) { 130 | throw new ElasticsearchException("注解ESField的type属性未指定"); 131 | } 132 | builder.startObject(name); 133 | { 134 | builder.field("type", esFieldType.typeName); 135 | // 分词器 136 | String analyzer = esField.getString("analyzer"); 137 | if (StringUtils.hasText(analyzer)) { 138 | builder.field("analyzer", analyzer); 139 | } 140 | } 141 | builder.endObject(); 142 | } 143 | } 144 | } 145 | builder.endObject(); 146 | } 147 | builder.endObject(); 148 | request.source(builder); 149 | 150 | AcknowledgedResponse putMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT); 151 | log.info("acknowledged : :{}", putMappingResponse.isAcknowledged()); 152 | 153 | } catch (IOException e) { 154 | e.printStackTrace(); 155 | } 156 | } 157 | 158 | 159 | public void deleteIndexRequest(String index) { 160 | DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(index); 161 | try { 162 | client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT); 163 | } catch (IOException e) { 164 | throw new ElasticsearchException("删除索引 {" + index + "} 失败"); 165 | } 166 | } 167 | 168 | public static IndexRequest buildIndexRequest(String index, String id, Object object) { 169 | return new IndexRequest(index).id(id).source(JSON.toJSONString(object), XContentType.JSON); 170 | } 171 | 172 | public void updateRequest(String index, String id, Object object) { 173 | try { 174 | UpdateRequest updateRequest = new UpdateRequest(index, id).doc(JSON.toJSONString(object), XContentType.JSON); 175 | client.update(updateRequest, COMMON_OPTIONS); 176 | } catch (IOException e) { 177 | throw new ElasticsearchException("更新索引 {" + index + "} 数据 {" + object + "} 失败"); 178 | } 179 | } 180 | 181 | public void deleteRequest(String index, String id) { 182 | try { 183 | DeleteRequest deleteRequest = new DeleteRequest(index, id); 184 | client.delete(deleteRequest, COMMON_OPTIONS); 185 | } catch (IOException e) { 186 | throw new ElasticsearchException("删除索引 {" + index + "} 数据id {" + id + "} 失败"); 187 | } 188 | } 189 | 190 | public SearchResponse search(String index) { 191 | SearchRequest searchRequest = new SearchRequest(index); 192 | SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 193 | searchSourceBuilder.query(QueryBuilders.matchAllQuery()); 194 | searchRequest.source(searchSourceBuilder); 195 | SearchResponse searchResponse = null; 196 | try { 197 | searchResponse = client.search(searchRequest, COMMON_OPTIONS); 198 | } catch (IOException e) { 199 | e.printStackTrace(); 200 | } 201 | return searchResponse; 202 | } 203 | } 204 | --------------------------------------------------------------------------------