You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

README.md 8.9 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. # spring-boot-demo-elasticsearch
  2. 依赖 [spring-boot-demo-parent](../spring-boot-demo-parent)
  3. > 关于 ES 的更多内容,可以参考[官方文档](https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started.html)
  4. >
  5. > 本例对应博客文章地址,http://xkcoding.com/2018/01/12/elasticsearch_note.html
  6. ElasticSearch 的 demo 我这里没有使用 spring-data-elasticsearch,我使用的是原生的方式
  7. 操作 ElasticSearch 由很多种方式:
  8. 1. ES 官方提供的原生方式,**本例子使用这种方式**,这种方式的好处是高度自定义,并且可以使用最新的 ES 版本,缺点就是所有操作都得自己写。
  9. 2. 使用 Spring 官方提供的 spring-data-elasticsearch,这里给出地址 https://projects.spring.io/spring-data-elasticsearch/ ,采用的方式类似 JPA,并且为 SpringBoot 提供了一个 `spring-boot-starter-data-elasticsearch`,优点是操作 ES 的方式采用了 JPA 的方式,都已经封装好了,缺点是版本得随着官方慢慢迭代,不能使用 ES 的最新特性。
  10. ### pom.xml
  11. ```xml
  12. <?xml version="1.0" encoding="UTF-8"?>
  13. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  14. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  15. <modelVersion>4.0.0</modelVersion>
  16. <artifactId>spring-boot-demo-elasticsearch</artifactId>
  17. <version>0.0.1-SNAPSHOT</version>
  18. <packaging>jar</packaging>
  19. <name>spring-boot-demo-elasticsearch</name>
  20. <description>Demo project for Spring Boot</description>
  21. <parent>
  22. <groupId>com.xkcoding</groupId>
  23. <artifactId>spring-boot-demo-parent</artifactId>
  24. <version>0.0.1-SNAPSHOT</version>
  25. <relativePath>../spring-boot-demo-parent/pom.xml</relativePath>
  26. </parent>
  27. <properties>
  28. <!--默认 Spring-Boot 依赖的 ES 版本是 2.X 版本,这里采用最新版-->
  29. <elasticsearch.version>6.1.1</elasticsearch.version>
  30. </properties>
  31. <dependencies>
  32. <!-- ES -->
  33. <dependency>
  34. <groupId>org.elasticsearch.client</groupId>
  35. <artifactId>transport</artifactId>
  36. <version>${elasticsearch.version}</version>
  37. </dependency>
  38. <dependency>
  39. <groupId>org.apache.logging.log4j</groupId>
  40. <artifactId>log4j-core</artifactId>
  41. <version>2.7</version>
  42. </dependency>
  43. </dependencies>
  44. <build>
  45. <finalName>spring-boot-demo-elasticsearch</finalName>
  46. </build>
  47. </project>
  48. ```
  49. ### application.yml
  50. ```yaml
  51. server:
  52. port: 8080
  53. context-path: /demo
  54. elasticsearch:
  55. host: 127.0.0.1
  56. port: 9300
  57. cluster:
  58. name: xkcoding
  59. ```
  60. ElasticSearchConfig.java
  61. ```java
  62. /**
  63. * <p>
  64. * ES 的配置类
  65. * </p>
  66. *
  67. * @package: com.xkcoding.springbootdemoelasticsearch.config
  68. * @description: ES 的配置类
  69. * @author: yangkai.shen
  70. * @date: Created in 2018/1/18 下午4:41
  71. * @copyright: Copyright (c) 2018
  72. * @version: 0.0.1
  73. * @modified: yangkai.shen
  74. */
  75. @Configuration
  76. public class ElasticSearchConfig {
  77. @Value("${elasticsearch.host}")
  78. private String host;
  79. @Value("${elasticsearch.port}")
  80. private int port;
  81. @Value("${elasticsearch.cluster.name}")
  82. private String clusterName;
  83. @Bean
  84. public TransportClient esClient() throws UnknownHostException {
  85. Settings settings = Settings.builder().put("cluster.name", this.clusterName).put("client.transport.sniff", true).build();
  86. TransportAddress master = new TransportAddress(InetAddress.getByName(host), port);
  87. TransportClient client = new PreBuiltTransportClient(settings).addTransportAddress(master);
  88. return client;
  89. }
  90. }
  91. ```
  92. PersonController.java
  93. ```java
  94. /**
  95. * <p>
  96. * Person Controller
  97. * </p>
  98. *
  99. * @package: com.xkcoding.springbootdemoelasticsearch.web.controller
  100. * @description: Person Controller
  101. * @author: yangkai.shen
  102. * @date: Created in 2018/1/18 下午5:06
  103. * @copyright: Copyright (c) 2018
  104. * @version: 0.0.1
  105. * @modified: yangkai.shen
  106. */
  107. @RestController
  108. @Slf4j
  109. public class PersonController {
  110. public static final String INDEX = "people";
  111. public static final String TYPE = "person";
  112. @Autowired
  113. private TransportClient esClient;
  114. /**
  115. * 插入一条数据到 ES 中,id 由 ES 生成
  116. *
  117. * @param name 名称
  118. * @param country 国籍
  119. * @param age 年龄
  120. * @param birthday 生日
  121. * @return 插入数据的主键
  122. */
  123. @PostMapping("/person")
  124. public ApiResponse add(@RequestParam String name, @RequestParam String country, @RequestParam Integer age, @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date birthday) {
  125. try {
  126. XContentBuilder content = XContentFactory.jsonBuilder().startObject().field("name", name).field("country", country).field("age", age).field("birthday", birthday.getTime()).endObject();
  127. IndexResponse response = esClient.prepareIndex(INDEX, TYPE).setSource(content).get();
  128. return ApiResponse.ofSuccess(response.getId());
  129. } catch (IOException e) {
  130. e.printStackTrace();
  131. return ApiResponse.ofStatus(Status.INTERNAL_SERVER_ERROR);
  132. }
  133. }
  134. /**
  135. * 根据 id 删除 ES 的一条记录
  136. *
  137. * @param id ES 中的 id
  138. * @return DELETED 代表删除
  139. */
  140. @DeleteMapping("/person/{id}")
  141. public ApiResponse delete(@PathVariable String id) {
  142. DeleteResponse response = esClient.prepareDelete(INDEX, TYPE, id).get();
  143. return ApiResponse.ofSuccess(response.getResult());
  144. }
  145. /**
  146. * 根据主键,修改传递字段对应的值
  147. *
  148. * @param id ES 中的 id
  149. * @param name 姓名
  150. * @param country 国籍
  151. * @param age 年龄
  152. * @param birthday 生日
  153. * @return UPDATED 代表文档修改成功
  154. */
  155. @PutMapping("/person/{id}")
  156. 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) {
  157. UpdateRequest request = new UpdateRequest(INDEX, TYPE, id);
  158. try {
  159. XContentBuilder builder = XContentFactory.jsonBuilder().startObject();
  160. if (!Strings.isNullOrEmpty(name)) {
  161. builder.field("name", name);
  162. }
  163. if (!Strings.isNullOrEmpty(country)) {
  164. builder.field("country", country);
  165. }
  166. if (age != null && age > 0) {
  167. builder.field("age", age);
  168. }
  169. if (birthday != null) {
  170. builder.field("birthday", birthday.getTime());
  171. }
  172. builder.endObject();
  173. request.doc(builder);
  174. } catch (IOException e) {
  175. e.printStackTrace();
  176. return ApiResponse.ofStatus(Status.INTERNAL_SERVER_ERROR);
  177. }
  178. try {
  179. UpdateResponse response = esClient.update(request).get();
  180. return ApiResponse.ofSuccess(response);
  181. } catch (Exception e) {
  182. e.printStackTrace();
  183. return ApiResponse.ofStatus(Status.INTERNAL_SERVER_ERROR);
  184. }
  185. }
  186. /**
  187. * 简单查询 根据 id 查 ES 中的文档内容
  188. *
  189. * @param id ES 中存储的 id
  190. * @return 对应 id 的文档内容
  191. */
  192. @GetMapping("/person/{id}")
  193. public ApiResponse get(@PathVariable String id) {
  194. GetResponse response = esClient.prepareGet(INDEX, TYPE, id).get();
  195. if (!response.isExists() || response.isSourceEmpty()) {
  196. return ApiResponse.ofStatus(Status.NOT_FOUND);
  197. }
  198. return ApiResponse.ofSuccess(response.getSource());
  199. }
  200. /**
  201. * 复合查询,根据传进来的条件,查询具体内容
  202. *
  203. * @param name 根据姓名匹配
  204. * @param country 根据国籍匹配
  205. * @param gtAge 大于年龄
  206. * @param ltAge 小于年龄
  207. * @return 满足条件的文档内容
  208. */
  209. @PostMapping("/person/query")
  210. public ApiResponse query(@RequestParam(value = "name", required = false) String name,
  211. @RequestParam(value = "country", required = false) String country,
  212. @RequestParam(value = "gt_age", defaultValue = "0") int gtAge,
  213. @RequestParam(value = "lt_age", required = false) Integer ltAge) {
  214. BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
  215. if (!Strings.isNullOrEmpty(name)) {
  216. boolQueryBuilder.must(QueryBuilders.matchQuery("name", name));
  217. }
  218. if (!Strings.isNullOrEmpty(country)) {
  219. boolQueryBuilder.must(QueryBuilders.matchQuery("country", country));
  220. }
  221. RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age").from(gtAge);
  222. if (ltAge != null && ltAge > 0) {
  223. rangeQueryBuilder.to(ltAge);
  224. }
  225. boolQueryBuilder.filter(rangeQueryBuilder);
  226. SearchRequestBuilder searchRequestBuilder = esClient.prepareSearch(INDEX)
  227. .setTypes(TYPE)
  228. .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
  229. .setQuery(boolQueryBuilder)
  230. .setFrom(0)
  231. .setSize(20);
  232. log.info("【query】:{}", searchRequestBuilder);
  233. SearchResponse searchResponse = searchRequestBuilder.get();
  234. List<Map<String, Object>> result = Lists.newArrayList();
  235. searchResponse.getHits().forEach(hit -> {
  236. result.add(hit.getSourceAsMap());
  237. });
  238. return ApiResponse.ofSuccess(result);
  239. }
  240. }
  241. ```

一个用来深度学习并实战 spring boot 的项目,目前总共包含 66 个集成demo,已经完成 55 个。

Contributors (1)