当前位置:   article > 正文

SpringBoot整合Elasticsearch_elasticsearch整合springboot

elasticsearch整合springboot

一、环境配置

Spring Boot与Elasticsearch整合的官方文档:Spring Data Elasticsearch

Spring Boot与Elasticsearch的版本要匹配对应,否则后面会出问题。

下表显示了 Spring Data release trains 的 Elasticsearch 版本和其中包含的 Spring Data Elasticsearch 版本,以及引用该特定 Spring Data release trains 的 Spring Boot 版本:

这里使用的是 SpringBoot-2.3.4.RELEASE 和 ElasticSearch-7.6.2

1. 引入依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-test</artifactId>
  8. <scope>test</scope>
  9. </dependency>

2. 配置 application.yml 文件

  1. server:
  2. port: 8033
  3. spring:
  4. elasticsearch:
  5. rest:
  6. uris: 192.168.1.179:9200

二、基于Java的Elasticsearch增删改查(ElasticsearchRestTemplate 方式)

1. 创建实体类 Stu.java 

  1. @Document(indexName = "stu", shards = 3, replicas = 0)
  2. public class Stu {
  3. @Id
  4. private Long stuId;
  5. @Field(store = true, analyzer = "ik_max_word", type = FieldType.Text)
  6. private String name;
  7. @Field(store = true, type = FieldType.Integer)
  8. private Integer age;
  9. @Field
  10. private Float money;
  11. @Field
  12. private boolean isMarried;
  13. // getter、setter、toString() 省略
  14. }
  • @Document定义在Elasticsearch中索引信息
  • @Id定义了Elasticsearch的_id
  • @Field定义字段类型等信息
  • …更多注解请参照官方文档…

2. 创建测试类 ESTest.java

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest(classes = Application.class)
  3. public class ESTest {
  4. @Autowired
  5. private ElasticsearchRestTemplate esTemplate;
  6. ......
  7. }

这里使用 ElasticsearchRestTemplate 方式执行增删改查

2.1 创建索引

  1. @Test
  2. public void createIndex(){
  3. esTemplate.indexOps(Stu.class).create();
  4. }

2.2 删除索引

  1. @Test
  2. public void deleteIndex() {
  3. esTemplate.indexOps(Stu.class).delete();
  4. }

2.3 判断索引是否存在

  1. @Test
  2. public void existIndex() {
  3. boolean isExist = esTemplate.indexOps(Stu.class).exists();
  4. System.out.println(isExist);
  5. }

2.4 新增文档数据

  1. @Test
  2. public void addDoc() {
  3. Stu stu0 = new Stu(10010L, "didiok", 18, 100.5f, true);
  4. esTemplate.save(stu0);
  5. Stu stu1 = new Stu(10011L, "Rede", 20, 88.5f, true);
  6. Stu stu2 = new Stu(10012L, "放下", 22, 108.5f, false);
  7. List<Stu> stuList = new ArrayList<>();
  8. stuList.add(stu1);
  9. stuList.add(stu2);
  10. esTemplate.save(stuList);
  11. }

2.5 根据文档id删除数据

  1. @Test
  2. public void deleteDoc(){
  3. esTemplate.delete("10010", Stu.class);
  4. }

2.6 查询文档数据

  1. @Test
  2. public void getDoc(){
  3. System.out.println(esTemplate.get("10011", Stu.class));
  4. }

2.7 修改文档数据

  1. @Test
  2. public void updateDoc(){
  3. Map<String, Object> stuMap = new HashMap<>();
  4. stuMap.put("name", "秦王嬴政");
  5. stuMap.put("age", 2000);
  6. Document doc = Document.from(stuMap);
  7. UpdateQuery updateQuery = UpdateQuery.builder("10011")
  8. .withDocument(doc)
  9. .build();
  10. IndexCoordinates indexCoordinate = IndexCoordinates.of("stu");
  11. esTemplate.update(updateQuery, indexCoordinate);
  12. }

2.8 搜索数据

  1. /**
  2. * 搜索数据
  3. */
  4. @Test
  5. public void searchStu(){
  6. Pageable pageable = PageRequest.of(0, 10);
  7. SortBuilder sortBuilder = new FieldSortBuilder("money")
  8. .order(SortOrder.ASC);
  9. SortBuilder sortBuilderName = new FieldSortBuilder("name.keyword") # name 有两种类型:text和keyword,其中name.keyword是指其为keyword类型的字段
  10. .order(SortOrder.DESC);
  11. NativeSearchQuery query =new NativeSearchQueryBuilder()
  12. .withQuery(QueryBuilders.matchQuery("name", "美丽 漂亮"))
  13. .withPageable(pageable)
  14. .withSort(sortBuilder)
  15. .withSort(sortBuilderName)
  16. .build();
  17. SearchHits<Stu> hits = esTemplate.search(query, Stu.class);
  18. System.out.println(hits.getSearchHits());
  19. }

2.9 高亮搜索

  1. @Test
  2. public void highlight(){
  3. String preTag = "<font color='red'>";
  4. String postTag = "</font>";
  5. NativeSearchQuery query = new NativeSearchQueryBuilder()
  6. .withQuery(QueryBuilders.matchQuery("name", "美丽可爱"))
  7. .withHighlightFields(new HighlightBuilder.Field("name")
  8. .preTags(preTag)
  9. .postTags(postTag))
  10. .build();
  11. SearchHits<Stu> hits = esTemplate.search(query, Stu.class);
  12. List<SearchHit<Stu>> stuHits = hits.getSearchHits();
  13. List<Stu> hlList = new ArrayList<>();
  14. for(SearchHit<Stu> h : stuHits){
  15. List<String> hlField = h.getHighlightField("name");
  16. String hlValue = hlField.get(0);
  17. Stu content = h.getContent();
  18. content.setName(hlValue);
  19. hlList.add(content);
  20. }
  21. System.out.println(hlList);
  22. }

三、基于Java的Elasticsearch增删改查(Elasticsearch Repositories方式)

1. 创建实体类

  1. @Document(indexName = "stu", shards = 3, replicas = 0)
  2. public class Stu {
  3. @Id
  4. private Long stuId;
  5. @Field(store = true, analyzer = "ik_max_word", type = FieldType.Text)
  6. private String name;
  7. @Field(store = true, type = FieldType.Integer)
  8. private Integer age;
  9. @Field
  10. private Float money;
  11. @Field
  12. private boolean isMarried;
  13. // getter、setter、toString() 省略
  14. }

2. 创建 mapper 层

  1. /**
  2. * @Author: liuss
  3. * @DateTime: 2023-04-22 13:34
  4. * @Description:
  5. * ElasticsearchRepository<T, ID> T:实体类泛型,ID:ES库中索引的主键类型
  6. */
  7. public interface StuMapper extends ElasticsearchRepository<Stu, String> {
  8. }

3. 增删改查

3.1 ElasticsearchRepository本身自带了一些简单curd方法,如下图

使用es自带的方法:

  1. @Test
  2. public void searchStu2(){
  3. Optional<Stu> stu = stuMapper.findById("10021");
  4. Iterable<Stu> stu2 = stuMapper.findAll();
  5. System.out.println(stu);
  6. System.out.println(stu2);
  7. }

 3.2 使用自定义的方法        

ES在方法名中支持的关键字
KeywordSampleElasticsearch Query String

And

findByNameAndPrice

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } }, { "query_string" : { "query" : "?", "fields" : [ "price" ] } } ] } }}

Or

findByNameOrPrice

{ "query" : { "bool" : { "should" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } }, { "query_string" : { "query" : "?", "fields" : [ "price" ] } } ] } }}

Is

findByName

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } } ] } }}

Not

findByNameNot

{ "query" : { "bool" : { "must_not" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } } ] } }}

Between

findByPriceBetween

{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }}

LessThan

findByPriceLessThan

{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : false } } } ] } }}

LessThanEqual

findByPriceLessThanEqual

{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }}

GreaterThan

findByPriceGreaterThan

{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : false, "include_upper" : true } } } ] } }}

GreaterThanEqual

findByPriceGreaterThan

{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : true, "include_upper" : true } } } ] } }}

Before

findByPriceBefore

{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }}

After

findByPriceAfter

{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : true, "include_upper" : true } } } ] } }}

Like

findByNameLike

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}

StartingWith

findByNameStartingWith

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}

EndingWith

findByNameEndingWith

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "*?", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}

Contains/Containing

findByNameContaining

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "*?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}

In (when annotated as FieldType.Keyword)

findByNameIn(Collection<String>names)

{ "query" : { "bool" : { "must" : [ {"bool" : {"must" : [ {"terms" : {"name" : ["?","?"]}} ] } } ] } }}

In

findByNameIn(Collection<String>names)

{ "query": {"bool": {"must": [{"query_string":{"query": "\"?\" \"?\"", "fields": ["name"]}}]}}}

NotIn (when annotated as FieldType.Keyword)

findByNameNotIn(Collection<String>names)

{ "query" : { "bool" : { "must" : [ {"bool" : {"must_not" : [ {"terms" : {"name" : ["?","?"]}} ] } } ] } }}

NotIn

findByNameNotIn(Collection<String>names)

{"query": {"bool": {"must": [{"query_string": {"query": "NOT(\"?\" \"?\")", "fields": ["name"]}}]}}}

Near

findByStoreNear

Not Supported Yet !

True

findByAvailableTrue

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "true", "fields" : [ "available" ] } } ] } }}

False

findByAvailableFalse

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "false", "fields" : [ "available" ] } } ] } }}

OrderBy

findByAvailableTrueOrderByNameDesc

{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "true", "fields" : [ "available" ] } } ] } }, "sort":[{"name":{"order":"desc"}}] }

可以自定义方法如下:

  1. public interface StuMapper extends ElasticsearchRepository<Stu, String> {
  2. List<Stu> findStusByName(String name);
  3. }

使用自定义方法查询:

  1. @Test
  2. public void searchStu3(){
  3. List<Stu> stus = stuMapper.findStusByName("didiok");
  4. System.out.println(stus);
  5. }

这只是其中一部分,更多内容可以参照官方文档:Spring Data Elasticsearch

完整代码如下:

  1. package com.test;
  2. import java.util.*;
  3. import org.elasticsearch.index.query.QueryBuilders;
  4. import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
  5. import org.elasticsearch.search.sort.FieldSortBuilder;
  6. import org.elasticsearch.search.sort.SortBuilder;
  7. import org.elasticsearch.search.sort.SortOrder;
  8. import org.junit.Test;
  9. import org.junit.runner.RunWith;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.boot.json.GsonJsonParser;
  12. import org.springframework.boot.json.JsonParser;
  13. import org.springframework.boot.test.context.SpringBootTest;
  14. import org.springframework.data.domain.PageRequest;
  15. import org.springframework.data.domain.Pageable;
  16. import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
  17. import org.springframework.data.elasticsearch.core.SearchHit;
  18. import org.springframework.data.elasticsearch.core.SearchHits;
  19. import org.springframework.data.elasticsearch.core.document.Document;
  20. import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
  21. import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
  22. import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
  23. import org.springframework.data.elasticsearch.core.query.UpdateQuery;
  24. import org.springframework.test.context.junit4.SpringRunner;
  25. import com.didiok.Application;
  26. import com.didiok.es.mapper.StuMapper;
  27. import com.didiok.es.pojo.Stu;
  28. import com.didiok.utils.JsonUtils;
  29. /**
  30. * @Author: liuss
  31. * @DateTime: 2023-04-21 16:47
  32. * @Description:
  33. */
  34. @RunWith(SpringRunner.class)
  35. @SpringBootTest(classes = Application.class)
  36. public class ESTest {
  37. @Autowired
  38. private ElasticsearchRestTemplate esTemplate;
  39. /**
  40. * 创建索引
  41. */
  42. @Test
  43. public void createIndex(){
  44. esTemplate.indexOps(Stu.class).create();
  45. }
  46. /**
  47. * 删除索引
  48. */
  49. @Test
  50. public void deleteIndex() {
  51. esTemplate.indexOps(Stu.class).delete();
  52. }
  53. /**
  54. * 判断索引是否存在
  55. */
  56. @Test
  57. public void existIndex() {
  58. boolean isExist = esTemplate.indexOps(Stu.class).exists();
  59. System.out.println(isExist);
  60. }
  61. /**
  62. * 新增文档数据
  63. */
  64. @Test
  65. public void addDoc() {
  66. Stu stu0 = new Stu(10010L, "didiok", 18, 100.5f, true);
  67. esTemplate.save(stu0);
  68. Stu stu1 = new Stu(10011L, "Rede", 20, 88.5f, true);
  69. Stu stu2 = new Stu(10012L, "放下", 22, 108.5f, false);
  70. List<Stu> stuList = new ArrayList<>();
  71. stuList.add(stu1);
  72. stuList.add(stu2);
  73. esTemplate.save(stuList);
  74. }
  75. /**
  76. * 根据文档id删除数据
  77. */
  78. @Test
  79. public void deleteDoc(){
  80. esTemplate.delete("10010", Stu.class);
  81. }
  82. /**
  83. * 查询文档数据
  84. */
  85. @Test
  86. public void getDoc(){
  87. System.out.println(esTemplate.get("10011", Stu.class));
  88. }
  89. /**
  90. * 修改文档数据
  91. */
  92. @Test
  93. public void updateDoc(){
  94. Map<String, Object> stuMap = new HashMap<>();
  95. stuMap.put("name", "秦王嬴政");
  96. stuMap.put("age", 2000);
  97. Document doc = Document.from(stuMap);
  98. UpdateQuery updateQuery = UpdateQuery.builder("10011")
  99. .withDocument(doc)
  100. .build();
  101. IndexCoordinates indexCoordinate = IndexCoordinates.of("stu");
  102. esTemplate.update(updateQuery, indexCoordinate);
  103. }
  104. /******************** 分词搜索 ********************/
  105. /**
  106. * 初始化数据
  107. */
  108. @Test
  109. public void init() {
  110. esTemplate.indexOps(Stu.class).delete();
  111. esTemplate.indexOps(Stu.class).create();
  112. Stu stu0 = new Stu(10020L, "didiok", 18, 100.5f, true);
  113. Stu stu1 = new Stu(10021L, "放下", 20, 88.5f, true);
  114. Stu stu2 = new Stu(10022L, "里德先生", 22, 96.5f, false);
  115. Stu stu3 = new Stu(10023L, "可爱的漂亮的小哥哥", 26, 108.5f, false);
  116. Stu stu4 = new Stu(10024L, "美丽的祖国", 28, 108.6f, true);
  117. Stu stu5 = new Stu(10025L, "美丽的漂亮的小姐姐", 16, 18.5f, false);
  118. Stu stu6 = new Stu(10026L, "超级赛亚人", 29, 100.5f, true);
  119. List<Stu> stuList = new ArrayList<>();
  120. stuList.add(stu0);
  121. stuList.add(stu1);
  122. stuList.add(stu2);
  123. stuList.add(stu3);
  124. stuList.add(stu4);
  125. stuList.add(stu5);
  126. stuList.add(stu6);
  127. esTemplate.save(stuList);
  128. }
  129. /**
  130. * 搜索数据
  131. */
  132. @Test
  133. public void searchStu(){
  134. Pageable pageable = PageRequest.of(0, 10);
  135. SortBuilder sortBuilder = new FieldSortBuilder("money")
  136. .order(SortOrder.DESC);
  137. SortBuilder sortBuilderName = new FieldSortBuilder("name.keyword")
  138. .order(SortOrder.ASC);
  139. NativeSearchQuery query =new NativeSearchQueryBuilder()
  140. .withQuery(QueryBuilders.matchQuery("name", "美丽 漂亮"))
  141. .withPageable(pageable)
  142. .withSort(sortBuilder)
  143. .withSort(sortBuilderName)
  144. .build();
  145. SearchHits<Stu> hits = esTemplate.search(query, Stu.class);
  146. System.out.println(hits.getSearchHits());
  147. }
  148. /**
  149. * 高亮搜索
  150. */
  151. @Test
  152. public void highlight(){
  153. String preTag = "<font color='red'>";
  154. String postTag = "</font>";
  155. NativeSearchQuery query = new NativeSearchQueryBuilder()
  156. .withQuery(QueryBuilders.matchQuery("name", "美丽可爱"))
  157. .withHighlightFields(new HighlightBuilder.Field("name")
  158. .preTags(preTag)
  159. .postTags(postTag))
  160. .build();
  161. SearchHits<Stu> hits = esTemplate.search(query, Stu.class);
  162. List<SearchHit<Stu>> stuHits = hits.getSearchHits();
  163. List<Stu> hlList = new ArrayList<>();
  164. for(SearchHit<Stu> h : stuHits){
  165. List<String> hlField = h.getHighlightField("name");
  166. String hlValue = hlField.get(0);
  167. Stu content = h.getContent();
  168. content.setName(hlValue);
  169. // String contentJson = JsonUtils.objectToJson(h.getContent());
  170. // JsonParser jj = new GsonJsonParser();
  171. // Map<String, Object> hlMap = jj.parseMap(contentJson);
  172. // hlMap.put("name", hlValue);
  173. hlList.add(content);
  174. }
  175. System.out.println(hlList);
  176. }
  177. @Autowired
  178. private StuMapper stuMapper;
  179. /**
  180. * 使用ElasticsearchRepository自带的方法查询
  181. */
  182. @Test
  183. public void searchStu2(){
  184. Optional<Stu> stu = stuMapper.findById("10021");
  185. Iterable<Stu> stu2 = stuMapper.findAll();
  186. System.out.println(stu);
  187. System.out.println(stu2);
  188. }
  189. /**
  190. * 使用自定义方法查询
  191. */
  192. @Test
  193. public void searchStu3(){
  194. List<Stu> stus = stuMapper.findStusByName("didiok");
  195. System.out.println(stus);
  196. }
  197. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/936265
推荐阅读
相关标签
  

闽ICP备14008679号