| @@ -0,0 +1,25 @@ | |||
| /target/ | |||
| !.mvn/wrapper/maven-wrapper.jar | |||
| ### STS ### | |||
| .apt_generated | |||
| .classpath | |||
| .factorypath | |||
| .project | |||
| .settings | |||
| .springBeans | |||
| .sts4-cache | |||
| ### IntelliJ IDEA ### | |||
| .idea | |||
| *.iws | |||
| *.iml | |||
| *.ipr | |||
| ### NetBeans ### | |||
| /nbproject/private/ | |||
| /build/ | |||
| /nbbuild/ | |||
| /dist/ | |||
| /nbdist/ | |||
| /.nb-gradle/ | |||
| @@ -0,0 +1,473 @@ | |||
| # spring-boot-demo-elasticsearch-rest-high-level-client | |||
| > 此 demo 主要演示了 Spring Boot 如何集成 `elasticsearch-rest-high-level-client` 完成对 ElasticSearch 的基本CURD 操作 | |||
| ## elasticsearch 升级 | |||
| 先升级到 6.8,索引创建,设置 mapping 等操作加参数:include_type_name=true,然后滚动升级到 7,旧索引可以用 type 访问。具体可以参考: | |||
| https://www.elastic.co/cn/blog/moving-from-types-to-typeless-apis-in-elasticsearch-7-0 | |||
| https://www.elastic.co/guide/en/elasticsearch/reference/7.0/removal-of-types.html | |||
| ## 注意 | |||
| 作者编写本demo时,ElasticSearch版本为 `7.3.0`,使用 docker 运行,下面是所有步骤: | |||
| 1. 下载镜像:`docker pull elasticsearch:7.3.0` | |||
| 2. 下载安装 `docker-compose` | |||
| ``` | |||
| sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose | |||
| 参考文档: https://docs.docker.com/compose/install/ | |||
| ``` | |||
| 2. 编写docker-compose 文件 | |||
| ```yaml | |||
| version: "3" | |||
| services: | |||
| es7: | |||
| hostname: es7 | |||
| container_name: es7 | |||
| image: elasticsearch:7.3.0 | |||
| volumes: | |||
| - "/data/es7/logs:/usr/share/es7/logs:rw" | |||
| - "/data/es7/data:/usr/share/es7/data:rw" | |||
| restart: on-failure | |||
| ports: | |||
| - "9200:9200" | |||
| - "9300:9300" | |||
| environment: | |||
| cluster.name: elasticsearch | |||
| discovery.type: single-node | |||
| logging: | |||
| driver: "json-file" | |||
| options: | |||
| max-size: "50m" | |||
| ``` | |||
| 3. 启动: `docker-compose -f elasticsearch.yaml up -d` | |||
| ## pom.xml | |||
| ```xml | |||
| <?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> | |||
| <artifactId>spring-boot-demo</artifactId> | |||
| <groupId>com.xkcoding</groupId> | |||
| <version>1.0.0-SNAPSHOT</version> | |||
| </parent> | |||
| <artifactId>spring-boot-demo-elasticsearch-rest-high-level-client</artifactId> | |||
| <name>spring-boot-demo-elasticsearch-rest-high-level-client</name> | |||
| <description>Demo project for Spring Boot</description> | |||
| <properties> | |||
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |||
| <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | |||
| <java.version>1.8</java.version> | |||
| </properties> | |||
| <dependencies> | |||
| <dependency> | |||
| <groupId>org.springframework.boot</groupId> | |||
| <artifactId>spring-boot-starter</artifactId> | |||
| </dependency> | |||
| <!-- test --> | |||
| <dependency> | |||
| <groupId>org.springframework.boot</groupId> | |||
| <artifactId>spring-boot-starter-test</artifactId> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <!-- validator --> | |||
| <dependency> | |||
| <groupId>org.hibernate.validator</groupId> | |||
| <artifactId>hibernate-validator</artifactId> | |||
| <scope>compile</scope> | |||
| </dependency> | |||
| <!-- | |||
| You can easily generate your own configuration metadata file from items annotated with | |||
| @ConfigurationProperties by using the spring-boot-configuration-processor jar. | |||
| --> | |||
| <dependency> | |||
| <groupId>org.springframework.boot</groupId> | |||
| <artifactId>spring-boot-configuration-processor</artifactId> | |||
| </dependency> | |||
| <!-- 工具类 --> | |||
| <dependency> | |||
| <groupId>cn.hutool</groupId> | |||
| <artifactId>hutool-all</artifactId> | |||
| <version>4.6.6</version> | |||
| </dependency> | |||
| <!-- elasticsearch --> | |||
| <dependency> | |||
| <groupId>org.elasticsearch</groupId> | |||
| <artifactId>elasticsearch</artifactId> | |||
| <version>7.3.0</version> | |||
| </dependency> | |||
| <!-- elasticsearch-rest-client --> | |||
| <dependency> | |||
| <groupId>org.elasticsearch.client</groupId> | |||
| <artifactId>elasticsearch-rest-client</artifactId> | |||
| <version>7.3.0</version> | |||
| </dependency> | |||
| <!-- elasticsearch-rest-high-level-client --> | |||
| <dependency> | |||
| <groupId>org.elasticsearch.client</groupId> | |||
| <artifactId>elasticsearch-rest-high-level-client</artifactId> | |||
| <version>7.3.0</version> | |||
| <exclusions> | |||
| <exclusion> | |||
| <groupId>org.elasticsearch.client</groupId> | |||
| <artifactId>elasticsearch-rest-client</artifactId> | |||
| </exclusion> | |||
| <exclusion> | |||
| <groupId>org.elasticsearch</groupId> | |||
| <artifactId>elasticsearch</artifactId> | |||
| </exclusion> | |||
| </exclusions> | |||
| </dependency> | |||
| <!-- lombok --> | |||
| <dependency> | |||
| <groupId>org.projectlombok</groupId> | |||
| <artifactId>lombok</artifactId> | |||
| <optional>true</optional> | |||
| </dependency> | |||
| </dependencies> | |||
| </project> | |||
| ``` | |||
| ## Person.java | |||
| > 实体类 | |||
| > | |||
| ```java | |||
| package com.xkcoding.elasticsearch.model; | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Builder; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| import java.io.Serializable; | |||
| import java.util.Date; | |||
| /** | |||
| * Person | |||
| * | |||
| * @author fxbin | |||
| * @version v1.0 | |||
| * @since 2019/9/15 23:04 | |||
| */ | |||
| @Data | |||
| @Builder | |||
| @NoArgsConstructor | |||
| @AllArgsConstructor | |||
| public class Person implements Serializable { | |||
| private static final long serialVersionUID = 8510634155374943623L; | |||
| /** | |||
| * 主键 | |||
| */ | |||
| private Long id; | |||
| /** | |||
| * 名字 | |||
| */ | |||
| private String name; | |||
| /** | |||
| * 国家 | |||
| */ | |||
| private String country; | |||
| /** | |||
| * 年龄 | |||
| */ | |||
| private Integer age; | |||
| /** | |||
| * 生日 | |||
| */ | |||
| private Date birthday; | |||
| /** | |||
| * 介绍 | |||
| */ | |||
| private String remark; | |||
| } | |||
| ``` | |||
| ## PersonService.java | |||
| ```java | |||
| package com.xkcoding.elasticsearch.service; | |||
| import com.xkcoding.elasticsearch.model.Person; | |||
| import org.springframework.lang.Nullable; | |||
| import java.util.List; | |||
| /** | |||
| * PersonService | |||
| * | |||
| * @author fxbin | |||
| * @version v1.0 | |||
| * @since 2019/9/15 23:07 | |||
| */ | |||
| public interface PersonService { | |||
| /** | |||
| * create Index | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index name | |||
| */ | |||
| void createIndex(String index); | |||
| /** | |||
| * delete Index | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index name | |||
| */ | |||
| void deleteIndex(String index); | |||
| /** | |||
| * insert document source | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index name | |||
| * @param list data source | |||
| */ | |||
| void insert(String index, List<Person> list); | |||
| /** | |||
| * update document source | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index name | |||
| * @param list data source | |||
| */ | |||
| void update(String index, List<Person> list); | |||
| /** | |||
| * delete document source | |||
| * | |||
| * @author fxbin | |||
| * @param person delete data source and allow null object | |||
| */ | |||
| void delete(String index, @Nullable Person person); | |||
| /** | |||
| * search all doc records | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index name | |||
| * @return person list | |||
| */ | |||
| List<Person> searchList(String index); | |||
| } | |||
| ``` | |||
| ## PersonServiceImpl.java | |||
| > service 实现类型,基本CURD操作 | |||
| ```java | |||
| package com.xkcoding.elasticsearch.service.impl; | |||
| import cn.hutool.core.bean.BeanUtil; | |||
| import com.xkcoding.elasticsearch.model.Person; | |||
| import com.xkcoding.elasticsearch.service.BaseElasticsearchService; | |||
| import com.xkcoding.elasticsearch.service.PersonService; | |||
| import org.elasticsearch.action.index.IndexRequest; | |||
| import org.elasticsearch.action.search.SearchResponse; | |||
| import org.elasticsearch.search.SearchHit; | |||
| import org.springframework.stereotype.Service; | |||
| import org.springframework.util.ObjectUtils; | |||
| import java.io.IOException; | |||
| import java.util.ArrayList; | |||
| import java.util.Arrays; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| /** | |||
| * PersonServiceImpl | |||
| * | |||
| * @author fxbin | |||
| * @version v1.0 | |||
| * @since 2019/9/15 23:08 | |||
| */ | |||
| @Service | |||
| public class PersonServiceImpl extends BaseElasticsearchService implements PersonService { | |||
| @Override | |||
| public void createIndex(String index) { | |||
| createIndexRequest(index); | |||
| } | |||
| @Override | |||
| public void deleteIndex(String index) { | |||
| deleteIndexRequest(index); | |||
| } | |||
| @Override | |||
| public void insert(String index, List<Person> list) { | |||
| try { | |||
| list.forEach(person -> { | |||
| IndexRequest request = buildIndexRequest(index, String.valueOf(person.getId()), person); | |||
| try { | |||
| client.index(request, COMMON_OPTIONS); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| }); | |||
| } finally { | |||
| try { | |||
| client.close(); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| } | |||
| @Override | |||
| public void update(String index, List<Person> list) { | |||
| list.forEach(person -> { | |||
| updateRequest(index, String.valueOf(person.getId()), person); | |||
| }); | |||
| } | |||
| @Override | |||
| public void delete(String index, Person person) { | |||
| if (ObjectUtils.isEmpty(person)) { | |||
| // 如果person 对象为空,则删除全量 | |||
| searchList(index).forEach(p -> { | |||
| deleteRequest(index, String.valueOf(p.getId())); | |||
| }); | |||
| } | |||
| deleteRequest(index, String.valueOf(person.getId())); | |||
| } | |||
| @Override | |||
| public List<Person> searchList(String index) { | |||
| SearchResponse searchResponse = search(index); | |||
| SearchHit[] hits = searchResponse.getHits().getHits(); | |||
| List<Person> personList = new ArrayList<>(); | |||
| Arrays.stream(hits).forEach(hit -> { | |||
| Map<String, Object> sourceAsMap = hit.getSourceAsMap(); | |||
| Person person = BeanUtil.mapToBean(sourceAsMap, Person.class, true); | |||
| personList.add(person); | |||
| }); | |||
| return personList; | |||
| } | |||
| } | |||
| ``` | |||
| ## ElasticsearchApplicationTests.java | |||
| > 主要功能测试,参见service 注释说明 | |||
| ```java | |||
| package com.xkcoding.elasticsearch; | |||
| import com.xkcoding.elasticsearch.contants.ElasticsearchConstant; | |||
| import com.xkcoding.elasticsearch.model.Person; | |||
| import com.xkcoding.elasticsearch.service.PersonService; | |||
| 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; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| @RunWith(SpringRunner.class) | |||
| @SpringBootTest | |||
| public class ElasticsearchApplicationTests { | |||
| @Resource | |||
| private PersonService personService; | |||
| @Test | |||
| public void deleteIndexTest() { | |||
| personService.deleteIndex(ElasticsearchConstant.INDEX_NAME); | |||
| } | |||
| @Test | |||
| public void createIndexTest() { | |||
| personService.createIndex(ElasticsearchConstant.INDEX_NAME); | |||
| } | |||
| @Test | |||
| public void insertTest() { | |||
| List<Person> list = new ArrayList<>(); | |||
| list.add(Person.builder().age(11).birthday(new Date()).country("CN").id(1L).name("哈哈").remark("test1").build()); | |||
| list.add(Person.builder().age(22).birthday(new Date()).country("US").id(2L).name("hiahia").remark("test2").build()); | |||
| list.add(Person.builder().age(33).birthday(new Date()).country("ID").id(3L).name("呵呵").remark("test3").build()); | |||
| personService.insert(ElasticsearchConstant.INDEX_NAME, list); | |||
| } | |||
| @Test | |||
| public void updateTest() { | |||
| Person person = Person.builder().age(33).birthday(new Date()).country("ID_update").id(3L).name("呵呵update").remark("test3_update").build(); | |||
| List<Person> list = new ArrayList<>(); | |||
| list.add(person); | |||
| personService.update(ElasticsearchConstant.INDEX_NAME, list); | |||
| } | |||
| @Test | |||
| public void deleteTest() { | |||
| personService.delete(ElasticsearchConstant.INDEX_NAME, Person.builder().id(1L).build()); | |||
| } | |||
| @Test | |||
| public void searchListTest() { | |||
| List<Person> personList = personService.searchList(ElasticsearchConstant.INDEX_NAME); | |||
| System.out.println(personList); | |||
| } | |||
| } | |||
| ``` | |||
| ## 参考 | |||
| 1. ElasticSearch 官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html | |||
| 2. Java High Level REST Client:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.3/java-rest-high.html | |||
| @@ -49,6 +49,13 @@ | |||
| <artifactId>spring-boot-configuration-processor</artifactId> | |||
| </dependency> | |||
| <!-- 工具类 --> | |||
| <dependency> | |||
| <groupId>cn.hutool</groupId> | |||
| <artifactId>hutool-all</artifactId> | |||
| <version>4.6.6</version> | |||
| </dependency> | |||
| <!-- elasticsearch --> | |||
| <dependency> | |||
| <groupId>org.elasticsearch</groupId> | |||
| @@ -56,16 +63,23 @@ | |||
| <version>7.3.0</version> | |||
| </dependency> | |||
| <!-- elasticsearch-rest-client --> | |||
| <dependency> | |||
| <groupId>org.elasticsearch.client</groupId> | |||
| <artifactId>elasticsearch-rest-client</artifactId> | |||
| <version>7.3.0</version> | |||
| </dependency> | |||
| <!-- elasticsearch-rest-high-level-client --> | |||
| <dependency> | |||
| <groupId>org.elasticsearch.client</groupId> | |||
| <artifactId>elasticsearch-rest-high-level-client</artifactId> | |||
| <version>7.3.0</version> | |||
| <exclusions> | |||
| <!-- <exclusion>--> | |||
| <!-- <groupId>org.elasticsearch.client</groupId>--> | |||
| <!-- <artifactId>elasticsearch-rest-client</artifactId>--> | |||
| <!-- </exclusion>--> | |||
| <exclusion> | |||
| <groupId>org.elasticsearch.client</groupId> | |||
| <artifactId>elasticsearch-rest-client</artifactId> | |||
| </exclusion> | |||
| <exclusion> | |||
| <groupId>org.elasticsearch</groupId> | |||
| <artifactId>elasticsearch</artifactId> | |||
| @@ -1,4 +1,4 @@ | |||
| package com.xlcoding.elasticsearch; | |||
| package com.xkcoding.elasticsearch; | |||
| import org.springframework.boot.SpringApplication; | |||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
| @@ -1,6 +1,10 @@ | |||
| package com.xlcoding.elasticsearch.autoconfigure; | |||
| package com.xkcoding.elasticsearch.autoconfigure; | |||
| import org.apache.http.HttpHost; | |||
| import org.apache.http.auth.AuthScope; | |||
| import org.apache.http.auth.UsernamePasswordCredentials; | |||
| import org.apache.http.client.CredentialsProvider; | |||
| import org.apache.http.impl.client.BasicCredentialsProvider; | |||
| import org.elasticsearch.client.RestClient; | |||
| import org.elasticsearch.client.RestClientBuilder; | |||
| import org.elasticsearch.client.RestHighLevelClient; | |||
| @@ -78,6 +82,15 @@ public class ElasticsearchAutoConfiguration { | |||
| httpClientBuilder.setMaxConnPerRoute(elasticsearchProperties.getMaxConnectPerRoute()); | |||
| return httpClientBuilder; | |||
| }); | |||
| // Callback used the basic credential auth | |||
| ElasticsearchProperties.Account account = elasticsearchProperties.getAccount(); | |||
| if (!StringUtils.isEmpty(account.getUsername()) && !StringUtils.isEmpty(account.getUsername())) { | |||
| final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); | |||
| credentialsProvider.setCredentials(AuthScope.ANY, | |||
| new UsernamePasswordCredentials(account.getUsername(), account.getPassword())); | |||
| } | |||
| return new RestHighLevelClient(builder); | |||
| } | |||
| @@ -1,9 +1,6 @@ | |||
| package com.xlcoding.elasticsearch.autoconfigure; | |||
| package com.xkcoding.elasticsearch.autoconfigure; | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Builder; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| import lombok.*; | |||
| import org.springframework.boot.context.properties.ConfigurationProperties; | |||
| import org.springframework.stereotype.Component; | |||
| @@ -70,21 +67,40 @@ public class ElasticsearchProperties { | |||
| /** | |||
| * 索引配置信息 | |||
| */ | |||
| private Index index; | |||
| private Index index = new Index(); | |||
| /** | |||
| * 认证账户 | |||
| */ | |||
| private Account account = new Account(); | |||
| @Data | |||
| @Builder | |||
| public static class Index { | |||
| /** | |||
| * 分片数量 | |||
| */ | |||
| protected Integer numberOfShards = 3; | |||
| private Integer numberOfShards = 3; | |||
| /** | |||
| * 副本数量 | |||
| */ | |||
| protected Integer numberOfReplicas = 2; | |||
| private Integer numberOfReplicas = 2; | |||
| } | |||
| @Data | |||
| public static class Account { | |||
| /** | |||
| * 认证用户 | |||
| */ | |||
| private String username; | |||
| /** | |||
| * 认证密码 | |||
| */ | |||
| private String password; | |||
| } | |||
| @@ -1,4 +1,4 @@ | |||
| package com.xlcoding.elasticsearch.contants; | |||
| package com.xkcoding.elasticsearch.contants; | |||
| /** | |||
| * DataTypeTransfer | |||
| @@ -1,4 +1,4 @@ | |||
| package com.xlcoding.elasticsearch.contants; | |||
| package com.xkcoding.elasticsearch.contants; | |||
| /** | |||
| * ElasticsearchConstant | |||
| @@ -1,6 +1,6 @@ | |||
| package com.xlcoding.elasticsearch.exception; | |||
| package com.xkcoding.elasticsearch.exception; | |||
| import com.xlcoding.elasticsearch.model.ResultCode; | |||
| import com.xkcoding.elasticsearch.model.ResultCode; | |||
| import lombok.Getter; | |||
| /** | |||
| @@ -1,4 +1,4 @@ | |||
| package com.xlcoding.elasticsearch.model; | |||
| package com.xkcoding.elasticsearch.model; | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Builder; | |||
| @@ -1,4 +1,4 @@ | |||
| package com.xlcoding.elasticsearch.model; | |||
| package com.xkcoding.elasticsearch.model; | |||
| import lombok.Data; | |||
| import org.springframework.lang.Nullable; | |||
| @@ -1,4 +1,4 @@ | |||
| package com.xlcoding.elasticsearch.model; | |||
| package com.xkcoding.elasticsearch.model; | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Getter; | |||
| @@ -0,0 +1,170 @@ | |||
| package com.xkcoding.elasticsearch.service; | |||
| import com.xkcoding.elasticsearch.exception.ElasticsearchException; | |||
| import com.xkcoding.elasticsearch.autoconfigure.ElasticsearchProperties; | |||
| import com.xkcoding.elasticsearch.util.BeanUtils; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import org.elasticsearch.action.ActionListener; | |||
| import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; | |||
| import org.elasticsearch.action.delete.DeleteRequest; | |||
| import org.elasticsearch.action.index.IndexRequest; | |||
| import org.elasticsearch.action.search.SearchRequest; | |||
| import org.elasticsearch.action.search.SearchResponse; | |||
| import org.elasticsearch.action.update.UpdateRequest; | |||
| import org.elasticsearch.action.update.UpdateResponse; | |||
| import org.elasticsearch.client.HttpAsyncResponseConsumerFactory; | |||
| import org.elasticsearch.client.RequestOptions; | |||
| import org.elasticsearch.client.RestHighLevelClient; | |||
| import org.elasticsearch.client.indices.CreateIndexRequest; | |||
| import org.elasticsearch.client.indices.CreateIndexResponse; | |||
| import org.elasticsearch.common.settings.Settings; | |||
| import org.elasticsearch.common.xcontent.XContentType; | |||
| import org.elasticsearch.index.engine.Engine; | |||
| import org.elasticsearch.index.query.QueryBuilders; | |||
| import org.elasticsearch.search.builder.SearchSourceBuilder; | |||
| import javax.annotation.Resource; | |||
| import java.io.IOException; | |||
| /** | |||
| * BaseElasticsearchService | |||
| * | |||
| * @author fxbin | |||
| * @version 1.0v | |||
| * @since 2019/9/16 15:44 | |||
| */ | |||
| @Slf4j | |||
| public abstract class BaseElasticsearchService { | |||
| @Resource | |||
| protected RestHighLevelClient client; | |||
| @Resource | |||
| private ElasticsearchProperties elasticsearchProperties; | |||
| protected static final RequestOptions COMMON_OPTIONS; | |||
| static { | |||
| RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); | |||
| // 默认缓冲限制为100MB,此处修改为30MB。 | |||
| builder.setHttpAsyncResponseConsumerFactory( | |||
| new HttpAsyncResponseConsumerFactory | |||
| .HeapBufferedResponseConsumerFactory(30 * 1024 * 1024)); | |||
| COMMON_OPTIONS = builder.build(); | |||
| } | |||
| /** | |||
| * create elasticsearch index (asyc) | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index | |||
| */ | |||
| protected void createIndexRequest(String index) { | |||
| try { | |||
| CreateIndexRequest request = new CreateIndexRequest(index); | |||
| // Settings for this index | |||
| request.settings(Settings.builder() | |||
| .put("index.number_of_shards", elasticsearchProperties.getIndex().getNumberOfShards()) | |||
| .put("index.number_of_replicas", elasticsearchProperties.getIndex().getNumberOfReplicas())); | |||
| CreateIndexResponse createIndexResponse = client.indices().create(request, COMMON_OPTIONS); | |||
| log.info(" whether all of the nodes have acknowledged the request : {}", createIndexResponse.isAcknowledged()); | |||
| log.info(" Indicates whether the requisite number of shard copies were started for each shard in the index before timing out :{}", | |||
| createIndexResponse.isShardsAcknowledged()); | |||
| } catch (IOException e) { | |||
| throw new ElasticsearchException("创建索引 {" + index + "} 失败"); | |||
| } | |||
| } | |||
| /** | |||
| * delete elasticsearch index | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index name | |||
| */ | |||
| protected void deleteIndexRequest(String index) { | |||
| DeleteIndexRequest deleteIndexRequest = buildDeleteIndexRequest(index); | |||
| try { | |||
| client.indices().delete(deleteIndexRequest, COMMON_OPTIONS); | |||
| } catch (IOException e) { | |||
| throw new ElasticsearchException("删除索引 {" + index + "} 失败"); | |||
| } | |||
| } | |||
| /** | |||
| * build DeleteIndexRequest | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index name | |||
| */ | |||
| private static DeleteIndexRequest buildDeleteIndexRequest (String index) { | |||
| return new DeleteIndexRequest(index); | |||
| } | |||
| /** | |||
| * build IndexRequest | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index name | |||
| * @param id request object id | |||
| * @param object request object | |||
| * @return {@link org.elasticsearch.action.index.IndexRequest} | |||
| */ | |||
| protected static IndexRequest buildIndexRequest(String index, String id, Object object) { | |||
| return new IndexRequest(index).id(id).source(BeanUtils.toMap(object), XContentType.JSON); | |||
| } | |||
| /** | |||
| * exec updateRequest | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index name | |||
| * @param id Document id | |||
| * @param object request object | |||
| */ | |||
| protected void updateRequest(String index, String id, Object object) { | |||
| try { | |||
| UpdateRequest updateRequest = new UpdateRequest(index, id).doc(BeanUtils.toMap(object), XContentType.JSON); | |||
| client.update(updateRequest, COMMON_OPTIONS); | |||
| } catch (IOException e) { | |||
| throw new ElasticsearchException("更新索引 {" + index + "} 数据 {" + object + "} 失败"); | |||
| } | |||
| } | |||
| /** | |||
| * exec deleteRequest | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index name | |||
| * @param id Document id | |||
| */ | |||
| protected void deleteRequest(String index, String id) { | |||
| try { | |||
| DeleteRequest deleteRequest = new DeleteRequest(index, id); | |||
| client.delete(deleteRequest, COMMON_OPTIONS); | |||
| } catch (IOException e) { | |||
| throw new ElasticsearchException("删除索引 {" + index + "} 数据id {" + id + "} 失败"); | |||
| } | |||
| } | |||
| /** | |||
| * search all | |||
| * @param index elasticsearch index name | |||
| * @return {@link SearchResponse} | |||
| */ | |||
| protected SearchResponse search(String index) { | |||
| SearchRequest searchRequest = new SearchRequest(index); | |||
| SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); | |||
| searchSourceBuilder.query(QueryBuilders.matchAllQuery()); | |||
| searchRequest.source(searchSourceBuilder); | |||
| SearchResponse searchResponse = null; | |||
| try { | |||
| searchResponse = client.search(searchRequest, COMMON_OPTIONS); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return searchResponse; | |||
| } | |||
| } | |||
| @@ -0,0 +1,68 @@ | |||
| package com.xkcoding.elasticsearch.service; | |||
| import com.xkcoding.elasticsearch.model.Person; | |||
| import org.springframework.lang.Nullable; | |||
| import java.util.List; | |||
| /** | |||
| * PersonService | |||
| * | |||
| * @author fxbin | |||
| * @version v1.0 | |||
| * @since 2019/9/15 23:07 | |||
| */ | |||
| public interface PersonService { | |||
| /** | |||
| * create Index | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index name | |||
| */ | |||
| void createIndex(String index); | |||
| /** | |||
| * delete Index | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index name | |||
| */ | |||
| void deleteIndex(String index); | |||
| /** | |||
| * insert document source | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index name | |||
| * @param list data source | |||
| */ | |||
| void insert(String index, List<Person> list); | |||
| /** | |||
| * update document source | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index name | |||
| * @param list data source | |||
| */ | |||
| void update(String index, List<Person> list); | |||
| /** | |||
| * delete document source | |||
| * | |||
| * @author fxbin | |||
| * @param person delete data source and allow null object | |||
| */ | |||
| void delete(String index, @Nullable Person person); | |||
| /** | |||
| * search all doc records | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index name | |||
| * @return person list | |||
| */ | |||
| List<Person> searchList(String index); | |||
| } | |||
| @@ -0,0 +1,91 @@ | |||
| package com.xkcoding.elasticsearch.service.impl; | |||
| import cn.hutool.core.bean.BeanUtil; | |||
| import com.xkcoding.elasticsearch.model.Person; | |||
| import com.xkcoding.elasticsearch.service.BaseElasticsearchService; | |||
| import com.xkcoding.elasticsearch.service.PersonService; | |||
| import org.elasticsearch.action.index.IndexRequest; | |||
| import org.elasticsearch.action.search.SearchResponse; | |||
| import org.elasticsearch.search.SearchHit; | |||
| import org.springframework.stereotype.Service; | |||
| import org.springframework.util.ObjectUtils; | |||
| import java.io.IOException; | |||
| import java.util.ArrayList; | |||
| import java.util.Arrays; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| /** | |||
| * PersonServiceImpl | |||
| * | |||
| * @author fxbin | |||
| * @version v1.0 | |||
| * @since 2019/9/15 23:08 | |||
| */ | |||
| @Service | |||
| public class PersonServiceImpl extends BaseElasticsearchService implements PersonService { | |||
| @Override | |||
| public void createIndex(String index) { | |||
| createIndexRequest(index); | |||
| } | |||
| @Override | |||
| public void deleteIndex(String index) { | |||
| deleteIndexRequest(index); | |||
| } | |||
| @Override | |||
| public void insert(String index, List<Person> list) { | |||
| try { | |||
| list.forEach(person -> { | |||
| IndexRequest request = buildIndexRequest(index, String.valueOf(person.getId()), person); | |||
| try { | |||
| client.index(request, COMMON_OPTIONS); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| }); | |||
| } finally { | |||
| try { | |||
| client.close(); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| } | |||
| @Override | |||
| public void update(String index, List<Person> list) { | |||
| list.forEach(person -> { | |||
| updateRequest(index, String.valueOf(person.getId()), person); | |||
| }); | |||
| } | |||
| @Override | |||
| public void delete(String index, Person person) { | |||
| if (ObjectUtils.isEmpty(person)) { | |||
| // 如果person 对象为空,则删除全量 | |||
| searchList(index).forEach(p -> { | |||
| deleteRequest(index, String.valueOf(p.getId())); | |||
| }); | |||
| } | |||
| deleteRequest(index, String.valueOf(person.getId())); | |||
| } | |||
| @Override | |||
| public List<Person> searchList(String index) { | |||
| SearchResponse searchResponse = search(index); | |||
| SearchHit[] hits = searchResponse.getHits().getHits(); | |||
| List<Person> personList = new ArrayList<>(); | |||
| Arrays.stream(hits).forEach(hit -> { | |||
| Map<String, Object> sourceAsMap = hit.getSourceAsMap(); | |||
| Person person = BeanUtil.mapToBean(sourceAsMap, Person.class, true); | |||
| personList.add(person); | |||
| }); | |||
| return personList; | |||
| } | |||
| } | |||
| @@ -1,12 +1,10 @@ | |||
| package com.xlcoding.elasticsearch.util; | |||
| package com.xkcoding.elasticsearch.util; | |||
| import com.xlcoding.elasticsearch.model.Person; | |||
| import com.xkcoding.elasticsearch.model.Person; | |||
| import java.beans.BeanInfo; | |||
| import java.beans.IntrospectionException; | |||
| import java.beans.Introspector; | |||
| import java.beans.PropertyDescriptor; | |||
| import java.lang.reflect.InvocationTargetException; | |||
| import java.lang.reflect.Method; | |||
| import java.util.Map; | |||
| @@ -50,15 +48,34 @@ public class BeanUtils { | |||
| return map; | |||
| } | |||
| /** | |||
| * Java Bean to Map | |||
| * | |||
| * @author fxbin | |||
| * @param object Object | |||
| * @return Map | |||
| */ | |||
| public static Map<String,Object> toMap(Object object){ | |||
| Map<String, Object> map = MapUtils.newHashMap(); | |||
| try { | |||
| // 获取javaBean的BeanInfo对象 | |||
| BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass(),Object.class); | |||
| public static void main(String[] args) { | |||
| Person person = new Person(); | |||
| Map<String, Object> stringObjectMap = toFieldNameAndFieldTypeMap(person); | |||
| System.out.println(stringObjectMap); | |||
| // 获取属性描述器 | |||
| PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); | |||
| for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { | |||
| // 获取属性名 | |||
| String key = propertyDescriptor.getName(); | |||
| // 获取该属性的值 | |||
| Method readMethod = propertyDescriptor.getReadMethod(); | |||
| // 通过反射来调用javaBean定义的getName()方法 | |||
| Object value = readMethod.invoke(object); | |||
| map.put(key, value); | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return map; | |||
| } | |||
| } | |||
| @@ -1,4 +1,4 @@ | |||
| package com.xlcoding.elasticsearch.util; | |||
| package com.xkcoding.elasticsearch.util; | |||
| import java.util.HashMap; | |||
| import java.util.LinkedHashMap; | |||
| @@ -1,88 +0,0 @@ | |||
| package com.xlcoding.elasticsearch.service; | |||
| import com.xlcoding.elasticsearch.autoconfigure.ElasticsearchProperties; | |||
| import com.xlcoding.elasticsearch.exception.ElasticsearchException; | |||
| import com.xlcoding.elasticsearch.model.Person; | |||
| import com.xlcoding.elasticsearch.util.BeanUtils; | |||
| import com.xlcoding.elasticsearch.util.MapUtils; | |||
| import org.elasticsearch.action.index.IndexRequest; | |||
| import org.elasticsearch.client.indices.CreateIndexRequest; | |||
| import org.elasticsearch.common.settings.Settings; | |||
| import org.elasticsearch.common.xcontent.XContentBuilder; | |||
| import org.elasticsearch.common.xcontent.XContentFactory; | |||
| import javax.annotation.Resource; | |||
| import java.io.IOException; | |||
| import java.util.Map; | |||
| /** | |||
| * BaseElasticsearchService | |||
| * | |||
| * @author fxbin | |||
| * @version 1.0v | |||
| * @since 2019/9/16 15:44 | |||
| */ | |||
| public abstract class BaseElasticsearchService { | |||
| @Resource | |||
| private ElasticsearchProperties elasticsearchProperties; | |||
| /** | |||
| * create elasticsearch index | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index | |||
| */ | |||
| public void createIndex(String index, Person person) { | |||
| try { | |||
| CreateIndexRequest request = new CreateIndexRequest(index); | |||
| // Settings for this index | |||
| request.settings(Settings.builder() | |||
| .put("index.number_of_shards", elasticsearchProperties.getIndex().getNumberOfShards()) | |||
| .put("index.number_of_replicas", elasticsearchProperties.getIndex().getNumberOfReplicas())); | |||
| XContentBuilder builder = XContentFactory.jsonBuilder(); | |||
| builder.startObject(); | |||
| { | |||
| builder.startObject("properties"); | |||
| { | |||
| builder.startObject("message"); | |||
| { | |||
| Map<String, Object> map = | |||
| BeanUtils.toMap(person); | |||
| map.keySet().forEach(key -> { | |||
| try { | |||
| builder.field(key, "text"); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| }); | |||
| } | |||
| builder.endObject(); | |||
| } | |||
| builder.endObject(); | |||
| } | |||
| builder.endObject(); | |||
| request.mapping(builder); | |||
| } catch (IOException e) { | |||
| throw new ElasticsearchException("创建Elasticsearch索引 {" + index + "} 失败"); | |||
| } | |||
| } | |||
| /** | |||
| * build IndexRequest | |||
| * | |||
| * @author fxbin | |||
| * @param index elasticsearch index name | |||
| * @return {@link org.elasticsearch.action.index.IndexRequest} | |||
| */ | |||
| public IndexRequest buildIndexRequest(String index) { | |||
| return new IndexRequest(index); | |||
| } | |||
| } | |||
| @@ -1,11 +0,0 @@ | |||
| package com.xlcoding.elasticsearch.service; | |||
| /** | |||
| * PersonService | |||
| * | |||
| * @author fxbin | |||
| * @version v1.0 | |||
| * @since 2019/9/15 23:07 | |||
| */ | |||
| public interface PersonService { | |||
| } | |||
| @@ -1,14 +0,0 @@ | |||
| package com.xlcoding.elasticsearch.service.impl; | |||
| import com.xlcoding.elasticsearch.service.BaseElasticsearchService; | |||
| import com.xlcoding.elasticsearch.service.PersonService; | |||
| /** | |||
| * PersonServiceImpl | |||
| * | |||
| * @author fxbin | |||
| * @version v1.0 | |||
| * @since 2019/9/15 23:08 | |||
| */ | |||
| public class PersonServiceImpl extends BaseElasticsearchService implements PersonService { | |||
| } | |||
| @@ -0,0 +1,3 @@ | |||
| # Auto Configure | |||
| org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ | |||
| com.xkcoding.elasticsearch.autoconfigure.ElasticsearchAutoConfiguration | |||
| @@ -3,3 +3,9 @@ demo: | |||
| elasticsearch: | |||
| cluster-name: elasticsearch | |||
| cluster-nodes: 20.20.0.27:9201 | |||
| index: | |||
| number-of-replicas: 0 | |||
| number-of-shards: 3 | |||
| account: | |||
| username: | |||
| password: | |||
| @@ -1,17 +0,0 @@ | |||
| package com.xdcoding.elasticsearch; | |||
| import org.junit.Test; | |||
| import org.junit.runner.RunWith; | |||
| import org.springframework.boot.test.context.SpringBootTest; | |||
| import org.springframework.test.context.junit4.SpringRunner; | |||
| @RunWith(SpringRunner.class) | |||
| @SpringBootTest | |||
| public class ElasticsearchApplicationTests { | |||
| @Test | |||
| public void contextLoads() { | |||
| } | |||
| } | |||
| @@ -0,0 +1,64 @@ | |||
| package com.xkcoding.elasticsearch; | |||
| import com.xkcoding.elasticsearch.contants.ElasticsearchConstant; | |||
| import com.xkcoding.elasticsearch.model.Person; | |||
| import com.xkcoding.elasticsearch.service.PersonService; | |||
| 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; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| @RunWith(SpringRunner.class) | |||
| @SpringBootTest | |||
| public class ElasticsearchApplicationTests { | |||
| @Resource | |||
| private PersonService personService; | |||
| @Test | |||
| public void deleteIndexTest() { | |||
| personService.deleteIndex(ElasticsearchConstant.INDEX_NAME); | |||
| } | |||
| @Test | |||
| public void createIndexTest() { | |||
| personService.createIndex(ElasticsearchConstant.INDEX_NAME); | |||
| } | |||
| @Test | |||
| public void insertTest() { | |||
| List<Person> list = new ArrayList<>(); | |||
| list.add(Person.builder().age(11).birthday(new Date()).country("CN").id(1L).name("哈哈").remark("test1").build()); | |||
| list.add(Person.builder().age(22).birthday(new Date()).country("US").id(2L).name("hiahia").remark("test2").build()); | |||
| list.add(Person.builder().age(33).birthday(new Date()).country("ID").id(3L).name("呵呵").remark("test3").build()); | |||
| personService.insert(ElasticsearchConstant.INDEX_NAME, list); | |||
| } | |||
| @Test | |||
| public void updateTest() { | |||
| Person person = Person.builder().age(33).birthday(new Date()).country("ID_update").id(3L).name("呵呵update").remark("test3_update").build(); | |||
| List<Person> list = new ArrayList<>(); | |||
| list.add(person); | |||
| personService.update(ElasticsearchConstant.INDEX_NAME, list); | |||
| } | |||
| @Test | |||
| public void deleteTest() { | |||
| personService.delete(ElasticsearchConstant.INDEX_NAME, Person.builder().id(1L).build()); | |||
| } | |||
| @Test | |||
| public void searchListTest() { | |||
| List<Person> personList = personService.searchList(ElasticsearchConstant.INDEX_NAME); | |||
| System.out.println(personList); | |||
| } | |||
| } | |||