Browse Source

spring boot 集成 ElasticSearch,采用原生方式集成 ES

v-1.5.x
Yangkai.Shen 6 years ago
parent
commit
d370c794e1
13 changed files with 724 additions and 3 deletions
  1. +6
    -2
      README.md
  2. +1
    -0
      TODO.md
  3. +24
    -0
      spring-boot-demo-elasticsearch/.gitignore
  4. +280
    -0
      spring-boot-demo-elasticsearch/README.md
  5. +44
    -0
      spring-boot-demo-elasticsearch/pom.xml
  6. +26
    -0
      spring-boot-demo-elasticsearch/src/main/java/com/xkcoding/springbootdemoelasticsearch/SpringBootDemoElasticsearchApplication.java
  7. +46
    -0
      spring-boot-demo-elasticsearch/src/main/java/com/xkcoding/springbootdemoelasticsearch/config/ElasticSearchConfig.java
  8. +48
    -0
      spring-boot-demo-elasticsearch/src/main/java/com/xkcoding/springbootdemoelasticsearch/web/base/ApiResponse.java
  9. +29
    -0
      spring-boot-demo-elasticsearch/src/main/java/com/xkcoding/springbootdemoelasticsearch/web/base/Status.java
  10. +194
    -0
      spring-boot-demo-elasticsearch/src/main/java/com/xkcoding/springbootdemoelasticsearch/web/controller/PersonController.java
  11. +8
    -0
      spring-boot-demo-elasticsearch/src/main/resources/application.yml
  12. +16
    -0
      spring-boot-demo-elasticsearch/src/test/java/com/xkcoding/springbootdemoelasticsearch/SpringBootDemoElasticsearchApplicationTests.java
  13. +2
    -1
      spring-boot-demo-parent/pom.xml

+ 6
- 2
README.md View File

@@ -1,6 +1,6 @@
# Spring Boot Demo

spring boot demo 是一个用来学习 spring boot 的项目,已经集成 actuator(监控)、admin(可视化监控)、logback(日志)、aopLog(通过 AOP 记录 web 请求日志)、统一异常处理( json 级别和页面级别)、freemarker(模板引擎)、thymeleaf(模板引擎)、JPA(ORM 框架)、mybatis(ORM 框架)、redis-cache(缓存)、swagger(API 接口管理测试)、ureport2(中国式报表)、打包成 war 文件,后续会集成activemq,email,shiro,websocket,quartz,netty等模块。
spring boot demo 是一个用来学习 spring boot 的项目,已经集成 actuator(监控)、admin(可视化监控)、logback(日志)、aopLog(通过 AOP 记录 web 请求日志)、统一异常处理( json 级别和页面级别)、freemarker(模板引擎)、thymeleaf(模板引擎)、JPA(ORM 框架)、mybatis(ORM 框架)、redis-cache(缓存)、swagger(API 接口管理测试)、ureport2(中国式报表)、打包成 war 文件、集成 ElasticSearch(采用原生操作 ES 的方式),后续会集成activemq,email,shiro,websocket,quartz,netty等模块。

依赖的 Spring Boot 版本:

@@ -58,8 +58,11 @@ spring boot demo 是一个用来学习 spring boot 的项目,已经集成 actu
<module>../spring-boot-demo-orm-mybatis</module>
<module>../spring-boot-demo-cache-redis</module>
<module>../spring-boot-demo-swagger</module>
<module>../spring-boot-demo-rabc-shiro-mybatis</module>
<module>../spring-boot-demo-ureport2</module>
<module>../spring-boot-demo-war</module>
<module>../spring-boot-demo-util</module>
<module>../spring-boot-demo-elasticsearch</module>
</modules>

<parent>
@@ -122,7 +125,7 @@ spring boot demo 是一个用来学习 spring boot 的项目,已经集成 actu
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
<version>23.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
@@ -161,6 +164,7 @@ spring boot demo 是一个用来学习 spring boot 的项目,已经集成 actu
| [spring-boot-demo-swagger](./spring-boot-demo-swagger) | spring-boot 集成 [spring-boot-starter-swagger](https://github.com/SpringForAll/spring-boot-starter-swagger) (由大佬[翟永超](http://blog.didispace.com/)开源)用于统一管理、测试 API 接口 |
| [spring-boot-demo-ureport2](./spring-boot-demo-ureport2) | spring-boot 集成 [ureport2](https://github.com/youseries/ureport) 实现自定义报表(ureport2可以轻松实现复杂的中国式报表,功能十分强大) |
| [spring-boot-demo-war](./spring-boot-demo-war) | spring-boot 打成 war 包的配置 |
| [spring-boot-demo-elasticsearch](./spring-boot-demo-elasticsearch) | spring-boot 集成 ElasticSearch(采用原生操作 ES 的方式) |

# 官方提供的 starter 介绍



+ 1
- 0
TODO.md View File

@@ -39,6 +39,7 @@
- [ ] spring-boot-demo-async(Spring boot 实现异步调用)
- [ ] spring-boot-demo-dubbo(集成 dubbo)
- [x] ~~spring-boot-demo-war(打包成war包)~~
- [x] ~~spring-boot-demo-elasticsearch(集成 ElasticSearch,使用原生操作 ES 的方式)~~

### 备注


+ 24
- 0
spring-boot-demo-elasticsearch/.gitignore View File

@@ -0,0 +1,24 @@
target/
!.mvn/wrapper/maven-wrapper.jar

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr

### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
.nb-gradle/

+ 280
- 0
spring-boot-demo-elasticsearch/README.md View File

@@ -0,0 +1,280 @@
# spring-boot-demo-elasticsearch

依赖 [spring-boot-demo-parent](../spring-boot-demo-parent)

ElasticSearch 的 demo 我这里没有使用 spring-data-elasticsearch,我使用的是原生的方式

操作 ElasticSearch 由很多种方式:

1. ES 官方提供的原生方式,**本例子使用这种方式**,这种方式的好处是高度自定义,并且可以使用最新的 ES 版本,缺点就是所有操作都得自己写。
2. 使用 Spring 官方提供的 spring-data-elasticsearch,这里给出地址 https://projects.spring.io/spring-data-elasticsearch/ ,采用的方式类似 JPA,并且为 SpringBoot 提供了一个 `spring-boot-starter-data-elasticsearch`,优点是操作 ES 的方式采用了 JPA 的方式,都已经封装好了,缺点是版本得随着官方慢慢迭代,不能使用 ES 的最新特性。

### 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>

<artifactId>spring-boot-demo-elasticsearch</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>spring-boot-demo-elasticsearch</name>
<description>Demo project for Spring Boot</description>

<parent>
<groupId>com.xkcoding</groupId>
<artifactId>spring-boot-demo-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../spring-boot-demo-parent/pom.xml</relativePath>
</parent>

<properties>
<!--默认 Spring-Boot 依赖的 ES 版本是 2.X 版本,这里采用最新版-->
<elasticsearch.version>6.1.1</elasticsearch.version>
</properties>

<dependencies>
<!-- ES -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>${elasticsearch.version}</version>
</dependency>

<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>
</dependencies>

<build>
<finalName>spring-boot-demo-elasticsearch</finalName>
</build>

</project>
```

### application.yml

```yaml
server:
port: 8080
context-path: /demo
elasticsearch:
host: 127.0.0.1
port: 9300
cluster:
name: xkcoding
```

ElasticSearchConfig.java

```java
/**
* <p>
* ES 的配置类
* </p>
*
* @package: com.xkcoding.springbootdemoelasticsearch.config
* @description: ES 的配置类
* @author: yangkai.shen
* @date: Created in 2018/1/18 下午4:41
* @copyright: Copyright (c) 2018
* @version: 0.0.1
* @modified: yangkai.shen
*/
@Configuration
public class ElasticSearchConfig {
@Value("${elasticsearch.host}")
private String host;

@Value("${elasticsearch.port}")
private int port;

@Value("${elasticsearch.cluster.name}")
private String clusterName;

@Bean
public TransportClient esClient() throws UnknownHostException {
Settings settings = Settings.builder().put("cluster.name", this.clusterName).put("client.transport.sniff", true).build();

TransportAddress master = new TransportAddress(InetAddress.getByName(host), port);
TransportClient client = new PreBuiltTransportClient(settings).addTransportAddress(master);
return client;
}
}
```

PersonController.java

```java
/**
* <p>
* Person Controller
* </p>
*
* @package: com.xkcoding.springbootdemoelasticsearch.web.controller
* @description: Person Controller
* @author: yangkai.shen
* @date: Created in 2018/1/18 下午5:06
* @copyright: Copyright (c) 2018
* @version: 0.0.1
* @modified: yangkai.shen
*/
@RestController
@Slf4j
public class PersonController {
public static final String INDEX = "people";
public static final String TYPE = "person";

@Autowired
private TransportClient esClient;

/**
* 插入一条数据到 ES 中,id 由 ES 生成
*
* @param name 名称
* @param country 国籍
* @param age 年龄
* @param birthday 生日
* @return 插入数据的主键
*/
@PostMapping("/person")
public ApiResponse add(@RequestParam String name, @RequestParam String country, @RequestParam Integer age, @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date birthday) {
try {
XContentBuilder content = XContentFactory.jsonBuilder().startObject().field("name", name).field("country", country).field("age", age).field("birthday", birthday.getTime()).endObject();

IndexResponse response = esClient.prepareIndex(INDEX, TYPE).setSource(content).get();
return ApiResponse.ofSuccess(response.getId());
} catch (IOException e) {
e.printStackTrace();
return ApiResponse.ofStatus(Status.INTERNAL_SERVER_ERROR);
}
}

/**
* 根据 id 删除 ES 的一条记录
*
* @param id ES 中的 id
* @return DELETED 代表删除
*/
@DeleteMapping("/person/{id}")
public ApiResponse delete(@PathVariable String id) {
DeleteResponse response = esClient.prepareDelete(INDEX, TYPE, id).get();
return ApiResponse.ofSuccess(response.getResult());
}

/**
* 根据主键,修改传递字段对应的值
*
* @param id ES 中的 id
* @param name 姓名
* @param country 国籍
* @param age 年龄
* @param birthday 生日
* @return UPDATED 代表文档修改成功
*/
@PutMapping("/person/{id}")
public ApiResponse update(@PathVariable String id, @RequestParam(value = "name", required = false) String name, @RequestParam(value = "country", required = false) String country, @RequestParam(value = "age", required = false) Integer age, @RequestParam(value = "birthday", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date birthday) {
UpdateRequest request = new UpdateRequest(INDEX, TYPE, id);
try {
XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
if (!Strings.isNullOrEmpty(name)) {
builder.field("name", name);
}
if (!Strings.isNullOrEmpty(country)) {
builder.field("country", country);
}
if (age != null && age > 0) {
builder.field("age", age);
}
if (birthday != null) {
builder.field("birthday", birthday.getTime());
}
builder.endObject();
request.doc(builder);
} catch (IOException e) {
e.printStackTrace();
return ApiResponse.ofStatus(Status.INTERNAL_SERVER_ERROR);
}
try {
UpdateResponse response = esClient.update(request).get();
return ApiResponse.ofSuccess(response);
} catch (Exception e) {
e.printStackTrace();
return ApiResponse.ofStatus(Status.INTERNAL_SERVER_ERROR);
}
}

/**
* 简单查询 根据 id 查 ES 中的文档内容
*
* @param id ES 中存储的 id
* @return 对应 id 的文档内容
*/
@GetMapping("/person/{id}")
public ApiResponse get(@PathVariable String id) {
GetResponse response = esClient.prepareGet(INDEX, TYPE, id).get();
if (!response.isExists() || response.isSourceEmpty()) {
return ApiResponse.ofStatus(Status.NOT_FOUND);
}
return ApiResponse.ofSuccess(response.getSource());
}

/**
* 复合查询,根据传进来的条件,查询具体内容
*
* @param name 根据姓名匹配
* @param country 根据国籍匹配
* @param gtAge 大于年龄
* @param ltAge 小于年龄
* @return 满足条件的文档内容
*/
@PostMapping("/person/query")
public ApiResponse query(@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "country", required = false) String country,
@RequestParam(value = "gt_age", defaultValue = "0") int gtAge,
@RequestParam(value = "lt_age", required = false) Integer ltAge) {
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

if (!Strings.isNullOrEmpty(name)) {
boolQueryBuilder.must(QueryBuilders.matchQuery("name", name));
}

if (!Strings.isNullOrEmpty(country)) {
boolQueryBuilder.must(QueryBuilders.matchQuery("country", country));
}

RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age").from(gtAge);

if (ltAge != null && ltAge > 0) {
rangeQueryBuilder.to(ltAge);
}

boolQueryBuilder.filter(rangeQueryBuilder);

SearchRequestBuilder searchRequestBuilder = esClient.prepareSearch(INDEX)
.setTypes(TYPE)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(boolQueryBuilder)
.setFrom(0)
.setSize(20);

log.info("【query】:{}", searchRequestBuilder);

SearchResponse searchResponse = searchRequestBuilder.get();
List<Map<String, Object>> result = Lists.newArrayList();
searchResponse.getHits().forEach(hit -> {
result.add(hit.getSourceAsMap());
});

return ApiResponse.ofSuccess(result);
}

}
```


+ 44
- 0
spring-boot-demo-elasticsearch/pom.xml View File

@@ -0,0 +1,44 @@
<?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>

<artifactId>spring-boot-demo-elasticsearch</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>spring-boot-demo-elasticsearch</name>
<description>Demo project for Spring Boot</description>

<parent>
<groupId>com.xkcoding</groupId>
<artifactId>spring-boot-demo-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../spring-boot-demo-parent/pom.xml</relativePath>
</parent>

<properties>
<!--默认 Spring-Boot 依赖的 ES 版本是 2.X 版本,这里采用最新版-->
<elasticsearch.version>6.1.1</elasticsearch.version>
</properties>

<dependencies>
<!-- ES -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>${elasticsearch.version}</version>
</dependency>

<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>
</dependencies>

<build>
<finalName>spring-boot-demo-elasticsearch</finalName>
</build>

</project>

+ 26
- 0
spring-boot-demo-elasticsearch/src/main/java/com/xkcoding/springbootdemoelasticsearch/SpringBootDemoElasticsearchApplication.java View File

@@ -0,0 +1,26 @@
package com.xkcoding.springbootdemoelasticsearch;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
* <p>
* 应用启动类
* </p>
*
* @package: com.xkcoding.springbootdemoelasticsearch.web.controller
* @description: 应用启动类
* @author: yangkai.shen
* @date: Created in 2018/1/18 下午5:06
* @copyright: Copyright (c) 2018
* @version: 0.0.1
* @modified: yangkai.shen
*/
@SpringBootApplication
public class SpringBootDemoElasticsearchApplication {

public static void main(String[] args) {
SpringApplication.run(SpringBootDemoElasticsearchApplication.class, args);
}

}

+ 46
- 0
spring-boot-demo-elasticsearch/src/main/java/com/xkcoding/springbootdemoelasticsearch/config/ElasticSearchConfig.java View File

@@ -0,0 +1,46 @@
package com.xkcoding.springbootdemoelasticsearch.config;

import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
* <p>
* ES 的配置类
* </p>
*
* @package: com.xkcoding.springbootdemoelasticsearch.config
* @description: ES 的配置类
* @author: yangkai.shen
* @date: Created in 2018/1/18 下午4:41
* @copyright: Copyright (c) 2018
* @version: 0.0.1
* @modified: yangkai.shen
*/
@Configuration
public class ElasticSearchConfig {
@Value("${elasticsearch.host}")
private String host;

@Value("${elasticsearch.port}")
private int port;

@Value("${elasticsearch.cluster.name}")
private String clusterName;

@Bean
public TransportClient esClient() throws UnknownHostException {
Settings settings = Settings.builder().put("cluster.name", this.clusterName).put("client.transport.sniff", true).build();

TransportAddress master = new TransportAddress(InetAddress.getByName(host), port);
TransportClient client = new PreBuiltTransportClient(settings).addTransportAddress(master);
return client;
}
}

+ 48
- 0
spring-boot-demo-elasticsearch/src/main/java/com/xkcoding/springbootdemoelasticsearch/web/base/ApiResponse.java View File

@@ -0,0 +1,48 @@
package com.xkcoding.springbootdemoelasticsearch.web.base;

import lombok.Data;

/**
* <p>
* 统一接口返回类型
* </p>
*
* @package: com.xkcoding.springbootdemoelasticsearch
* @description: 统一接口返回类型
* @author: yangkai.shen
* @date: Created in 2018/1/18 下午5:34
* @copyright: Copyright (c) 2018
* @version: 0.0.1
* @modified: yangkai.shen
*/
@Data
public class ApiResponse {
private int code;
private String message;
private Object data;
private boolean more;

public ApiResponse(int code, String message, Object data) {
this.code = code;
this.message = message;
this.data = data;
}

public ApiResponse() {
this.code = Status.SUCCESS.getCode();
this.message = Status.SUCCESS.getMsg();
}

public static ApiResponse ofMessage(int code, String message) {
return new ApiResponse(code, message, null);
}

public static ApiResponse ofSuccess(Object data) {
return new ApiResponse(Status.SUCCESS.getCode(), Status.SUCCESS.getMsg(), data);
}

public static ApiResponse ofStatus(Status status) {
return new ApiResponse(status.getCode(), status.getMsg(), null);
}

}

+ 29
- 0
spring-boot-demo-elasticsearch/src/main/java/com/xkcoding/springbootdemoelasticsearch/web/base/Status.java View File

@@ -0,0 +1,29 @@
package com.xkcoding.springbootdemoelasticsearch.web.base;

import lombok.Getter;

/**
* <p>
* 通用状态码
* </p>
*
* @package: com.xkcoding.springbootdemoelasticsearch.web.base
* @description: 通用状态码
* @author: yangkai.shen
* @date: Created in 2018/1/18 下午5:35
* @copyright: Copyright (c) 2018
* @version: 0.0.1
* @modified: yangkai.shen
*/
@Getter
public enum Status {
SUCCESS(200, "OK"), BAD_REQUEST(400, "Bad Request"), NOT_FOUND(404, "Not Found"), INTERNAL_SERVER_ERROR(500, "Unknown Internal Error");

private int code;
private String msg;

Status(int code, String msg) {
this.code = code;
this.msg = msg;
}
}

+ 194
- 0
spring-boot-demo-elasticsearch/src/main/java/com/xkcoding/springbootdemoelasticsearch/web/controller/PersonController.java View File

@@ -0,0 +1,194 @@
package com.xkcoding.springbootdemoelasticsearch.web.controller;

import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.xkcoding.springbootdemoelasticsearch.web.base.ApiResponse;
import com.xkcoding.springbootdemoelasticsearch.web.base.Status;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
* <p>
* Person Controller
* </p>
*
* @package: com.xkcoding.springbootdemoelasticsearch.web.controller
* @description: Person Controller
* @author: yangkai.shen
* @date: Created in 2018/1/18 下午5:06
* @copyright: Copyright (c) 2018
* @version: 0.0.1
* @modified: yangkai.shen
*/
@RestController
@Slf4j
public class PersonController {
public static final String INDEX = "people";
public static final String TYPE = "person";

@Autowired
private TransportClient esClient;

/**
* 插入一条数据到 ES 中,id 由 ES 生成
*
* @param name 名称
* @param country 国籍
* @param age 年龄
* @param birthday 生日
* @return 插入数据的主键
*/
@PostMapping("/person")
public ApiResponse add(@RequestParam String name, @RequestParam String country, @RequestParam Integer age, @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date birthday) {
try {
XContentBuilder content = XContentFactory.jsonBuilder().startObject().field("name", name).field("country", country).field("age", age).field("birthday", birthday.getTime()).endObject();

IndexResponse response = esClient.prepareIndex(INDEX, TYPE).setSource(content).get();
return ApiResponse.ofSuccess(response.getId());
} catch (IOException e) {
e.printStackTrace();
return ApiResponse.ofStatus(Status.INTERNAL_SERVER_ERROR);
}
}

/**
* 根据 id 删除 ES 的一条记录
*
* @param id ES 中的 id
* @return DELETED 代表删除
*/
@DeleteMapping("/person/{id}")
public ApiResponse delete(@PathVariable String id) {
DeleteResponse response = esClient.prepareDelete(INDEX, TYPE, id).get();
return ApiResponse.ofSuccess(response.getResult());
}

/**
* 根据主键,修改传递字段对应的值
*
* @param id ES 中的 id
* @param name 姓名
* @param country 国籍
* @param age 年龄
* @param birthday 生日
* @return UPDATED 代表文档修改成功
*/
@PutMapping("/person/{id}")
public ApiResponse update(@PathVariable String id, @RequestParam(value = "name", required = false) String name, @RequestParam(value = "country", required = false) String country, @RequestParam(value = "age", required = false) Integer age, @RequestParam(value = "birthday", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date birthday) {
UpdateRequest request = new UpdateRequest(INDEX, TYPE, id);
try {
XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
if (!Strings.isNullOrEmpty(name)) {
builder.field("name", name);
}
if (!Strings.isNullOrEmpty(country)) {
builder.field("country", country);
}
if (age != null && age > 0) {
builder.field("age", age);
}
if (birthday != null) {
builder.field("birthday", birthday.getTime());
}
builder.endObject();
request.doc(builder);
} catch (IOException e) {
e.printStackTrace();
return ApiResponse.ofStatus(Status.INTERNAL_SERVER_ERROR);
}
try {
UpdateResponse response = esClient.update(request).get();
return ApiResponse.ofSuccess(response);
} catch (Exception e) {
e.printStackTrace();
return ApiResponse.ofStatus(Status.INTERNAL_SERVER_ERROR);
}
}

/**
* 简单查询 根据 id 查 ES 中的文档内容
*
* @param id ES 中存储的 id
* @return 对应 id 的文档内容
*/
@GetMapping("/person/{id}")
public ApiResponse get(@PathVariable String id) {
GetResponse response = esClient.prepareGet(INDEX, TYPE, id).get();
if (!response.isExists() || response.isSourceEmpty()) {
return ApiResponse.ofStatus(Status.NOT_FOUND);
}
return ApiResponse.ofSuccess(response.getSource());
}

/**
* 复合查询,根据传进来的条件,查询具体内容
*
* @param name 根据姓名匹配
* @param country 根据国籍匹配
* @param gtAge 大于年龄
* @param ltAge 小于年龄
* @return 满足条件的文档内容
*/
@PostMapping("/person/query")
public ApiResponse query(@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "country", required = false) String country,
@RequestParam(value = "gt_age", defaultValue = "0") int gtAge,
@RequestParam(value = "lt_age", required = false) Integer ltAge) {
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

if (!Strings.isNullOrEmpty(name)) {
boolQueryBuilder.must(QueryBuilders.matchQuery("name", name));
}

if (!Strings.isNullOrEmpty(country)) {
boolQueryBuilder.must(QueryBuilders.matchQuery("country", country));
}

RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age").from(gtAge);

if (ltAge != null && ltAge > 0) {
rangeQueryBuilder.to(ltAge);
}

boolQueryBuilder.filter(rangeQueryBuilder);

SearchRequestBuilder searchRequestBuilder = esClient.prepareSearch(INDEX)
.setTypes(TYPE)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(boolQueryBuilder)
.setFrom(0)
.setSize(20);

log.info("【query】:{}", searchRequestBuilder);

SearchResponse searchResponse = searchRequestBuilder.get();
List<Map<String, Object>> result = Lists.newArrayList();
searchResponse.getHits().forEach(hit -> {
result.add(hit.getSourceAsMap());
});

return ApiResponse.ofSuccess(result);
}

}

+ 8
- 0
spring-boot-demo-elasticsearch/src/main/resources/application.yml View File

@@ -0,0 +1,8 @@
server:
port: 8080
context-path: /demo
elasticsearch:
host: 127.0.0.1
port: 9300
cluster:
name: xkcoding

+ 16
- 0
spring-boot-demo-elasticsearch/src/test/java/com/xkcoding/springbootdemoelasticsearch/SpringBootDemoElasticsearchApplicationTests.java View File

@@ -0,0 +1,16 @@
package com.xkcoding.springbootdemoelasticsearch;

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 SpringBootDemoElasticsearchApplicationTests {

@Test
public void contextLoads() {
}

}

+ 2
- 1
spring-boot-demo-parent/pom.xml View File

@@ -29,6 +29,7 @@
<module>../spring-boot-demo-ureport2</module>
<module>../spring-boot-demo-war</module>
<module>../spring-boot-demo-util</module>
<module>../spring-boot-demo-elasticsearch</module>
</modules>

<parent>
@@ -91,7 +92,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
<version>23.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>


Loading…
Cancel
Save