@@ -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); | |||
} | |||
} |