首页 > 其他分享 >Springboot 系列 (20) - Springboot+ElasticSearch 实现全文搜索(二)

Springboot 系列 (20) - Springboot+ElasticSearch 实现全文搜索(二)

时间:2022-12-05 22:13:41浏览次数:60  
标签:map 20 Springboot org elasticsearch import ElasticSearch response springboot


在 “Springboot 系列 (19) - Springboot+ElasticSearch 实现全文搜索(一)” 里我们演示了安装配置 ElasticSearch 和使用 curl 调用 ElasticSearch API,本文将演示在 Springboot 项目里如何调用 ElasticSearch API。

1. 配置 ElasticSearch

    1) 运行环境

        操作系统:Ubuntu 20.04
        内网 IP:192.168.0.10
        端口: 9200

        Java 版本: 1.8.0_341
        ElasticSearch 版本:7.10.2
        ElasticSearch 所在路径:~/apps/elasticsearch-7.10.2/

    2) 启动

        $ cd ~/apps/elasticsearch-7.10.2/bin
        $ ./elasticsearch

            ...

            ERROR: [2] bootstrap checks failed
            [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
            [2]: the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured

            ...


            注:启动失败,两个问题:1. jvm 内存不够大;2. 集群节点最低配置要求;

        # 增加 jvm 内存到 262144
        $ sudo sysctl -w vm.max_map_count=262144

            vm.max_map_count = 262144

        # 修改 elasticsearch.yml 文件,添加如下内容
        $ vim ~/apps/elasticsearch-7.10.2/config/elasticsearch.yml

            # 单机模式
            discovery.type: single-node

        # 再次启动
        $ ./elasticsearch


2. Springboot 开发环境

    Windows版本:Windows 10 Home (20H2)   
    IntelliJ IDEA (https://www.jetbrains.com/idea/download/):Community Edition for Windows 2020.1.4
    Apache Maven (https://maven.apache.org/):3.8.1

    注:Spring 开发环境的搭建,可以参考 “ Spring基础知识(1)- Spring简介、Spring体系结构和开发环境配置 ”。


3. 创建 Springboot 基础项目

    项目实例名称:SpringbootExample19
    Spring Boot 版本:2.6.6

    创建步骤:

        (1) 创建 Maven 项目实例 SpringbootExample19;
        (2) Spring Boot Web 配置;
        (3) 导入 Thymeleaf 依赖包;
        (4) 配置 jQuery;
        
    具体操作请参考 “Spring 系列 (2) - 在 Spring Boot 项目里使用 Thymeleaf、JQuery+Bootstrap 和国际化” 里的项目实例 SpringbootExample02,文末包含如何使用 spring-boot-maven-plugin 插件运行打包的内容。

    SpringbootExample19 和 SpringbootExample02 相比,SpringbootExample19 不配置 Bootstrap、模版文件(templates/*.html)和国际化。


4. 添加 Elasticsearch 依赖

    1) 修改 pom.xml,导入 Elasticsearch 依赖包

        <project ... >
            ...
            <dependencies>
                ...

                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
                </dependency>

                ...
            </dependencies>

            ...
        </project>

        在IDE中项目列表 -> SpringbootExample19 -> 点击鼠标右键 -> Maven -> Reload Project

    2) 修改 src/main/resources/application.properties 文件,添加如下配置

        # ElasticSearch
        spring.elasticsearch.rest.uris=192.168.0.10:9200
        spring.elasticsearch.rest.username=elastic
        spring.elasticsearch.rest.password=123456


5. 测试实例 (Web 模式)

    1) 创建 src/main/java/com/example/config/ElasticSearchRestClientConfig.java 文件

 1         package com.example.config;
 2 
 3         import org.springframework.beans.factory.annotation.Value;
 4         import org.springframework.context.annotation.Bean;
 5         import org.springframework.context.annotation.Configuration;
 6         import org.springframework.data.elasticsearch.client.ClientConfiguration;
 7         import org.springframework.data.elasticsearch.client.RestClients;
 8         import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
 9 
10         import org.elasticsearch.client.RestHighLevelClient;
11 
12         @Configuration
13         public class ElasticSearchRestClientConfig extends AbstractElasticsearchConfiguration {
14             @Value("${spring.elasticsearch.rest.uris}")
15             private String uris;
16             @Value("${spring.elasticsearch.rest.username}")
17             private String username;
18             @Value("${spring.elasticsearch.rest.password}")
19             private String password;
20 
21             @Override
22             @Bean
23             public RestHighLevelClient elasticsearchClient() {
24 
25                 final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
26                         .connectedTo(uris)
27                         .withBasicAuth(username, password)
28                         .build();
29 
30                 return RestClients.create(clientConfiguration).rest();
31             }
32 
33         }


    2) 创建 src/main/resources/templates/client.html 文件

  1         <html lang="en" xmlns:th="http://www.thymeleaf.org">
  2         <head>
  3             <meta charset="UTF-8">
  4             <title th:text="${var}">Title</title>
  5             <script language="javascript" th:src="@{/lib/jquery/jquery-3.6.0.min.js}"></script>
  6         </head>
  7         <body>
  8 
  9             <h3>ElasticSearch Client</h3>
 10             <hr>
 11             <p>
 12                 Operation:<br>
 13                 <select id="operation" name="operation" style="width: 50%;height: 32px;">
 14                     <option value=""></option>
 15                     <option value="create_springboot">1. 创建一个索引 "springboot"</option>
 16                     <option value="get_springboot">2. 查看 "springboot"</option>
 17                     <option value="delete_springboot">3. 删除 "springboot"</option>
 18                     <option value="create_springboot_settings">4. 创建一个带 settings 的索引 "springboot"</option>
 19                     <option value="get_springboot_settings">5. 查看带 settings 的 "springboot"</option>
 20                     <option value="create_doc1_auto">6. 在 "springboot/doc1" 下创建一个文档(自动生成 _id)</option>
 21                     <option value="create_doc1_2">7. 在 "springboot/doc1/2" 下创建一个文档(指定 _id 为 2)</option>
 22                     <option value="create_doc1_batch">8. 在 "springboot/doc1" 下批量创建文档(自动生成 _id)</option>
 23                     <option value="get_doc1_2">9. 查看 "springboot/doc1/2"</option>
 24                     <option value="modify_doc1_2">10. 修改 "springboot/doc1/2"</option>
 25                     <option value="delete_doc1_2">11. 删除 "springboot/doc1/2"</option>
 26                     <option value="query_springboot_docs">12. 查询 "springboot" 下的全部文档 </option>
 27                     <option value="term_query_springboot_docs">13. 精准查询 "springboot" 下 name="Elastic Search" (_id=2) 的文档  </option>
 28                     <option value="match_query_springboot_docs">14. 模糊查询 "springboot" 下 name 包含 "Elastic Search" 的文档  </option>
 29                 </select>
 30             </p>
 31             <p id="raw_area" style="display:none;">
 32                 Raw (JSON):<br>
 33                 <textarea name="raw" id="raw" rows="3" style="width: 50%;"></textarea>
 34             </p>
 35             <p id="raw_area_2" style="display:none;">
 36                 Raw 2 (JSON):<br>
 37                 <textarea name="raw2" id="raw2" rows="3" style="width: 50%;"></textarea>
 38             </p>
 39             <p>
 40                 <button type="button" id="btn_submit">Submit</button>
 41             </p>
 42 
 43             <div id="result" style="width: 98%; height: 420px; background-color: #f2f2f2; padding: 5px;"></div>
 44 
 45             <p>&nbsp;</p>
 46 
 47         <script type="text/javascript">
 48 
 49             $(document).ready(function(){
 50 
 51                 $('#btn_submit').click(function() {
 52 
 53                     var operation = $('#operation').val();
 54                     if (operation == '') {
 55                         alert('Please select operation');
 56                         $('#operation').focus();
 57                         return;
 58                     }
 59                     var raw = $('#raw').val();
 60                     var raw2 = $('#raw2').val();
 61 
 62                     $.ajax({
 63 
 64                         type: 'POST',
 65                         url: '/operation',
 66                         data: {
 67                             operation: operation,
 68                             raw: raw,
 69                             raw2: raw2
 70                         },
 71                         success: function(response) {
 72                             console.log(response);
 73                             if (response.ret == "OK") {
 74                                 $('#result').html("SUCCESS, (" + operation + "): " + response.description + "<br>");
 75                             } else {
 76                                 $('#result').html("FAILED, (" + operation + "): " + response.description + "<br>");
 77                             }
 78                         },
 79                         error: function(err) {
 80                             console.log(err);
 81                             $('#result').append("Error: " + err.responseText + "<br>");
 82                         }
 83                     });
 84                 });
 85 
 86                 $('#operation').change(function() {
 87 
 88                     var operation = $('#operation').val();
 89 
 90                     $('#raw_area').css('display', 'none');
 91                     $('#raw_area_2').css('display', 'none');
 92                     $('#raw').val('');
 93                     $('#raw2').val('');
 94 
 95                     if (operation == "create_springboot_settings") {
 96                         var strRaw = '{"number_of_shards":5,"number_of_replicas":1}';
 97                         $('#raw').val(strRaw);
 98                         $('#raw_area').css('display', '');
 99                     } else if (operation == "create_doc1_auto") {
100                         var d = Date.now();
101                         var strRaw = '{"name":"Elastic Search - ' + d + '","author":"Elastic Company","count":3}';
102                         $('#raw').val(strRaw);
103                         $('#raw_area').css('display', '');
104                     } else if (operation == "create_doc1_2") {
105                         var strRaw = '{"name":"Elastic Search","author":"Elastic Company","count":8}';
106                         $('#raw').val(strRaw);
107                         $('#raw_area').css('display', '');
108                     } else if (operation == "create_doc1_batch") {
109                         var strRaw = '{"name":"Elastic Search 2","author":"Elastic Company 2","count":11}';
110                         var strRaw2 = '{"name":"Elastic Search 3","author":"Elastic Company 3","count":22}';
111                         $('#raw').val(strRaw);
112                         $('#raw2').val(strRaw2);
113                         $('#raw_area').css('display', '');
114                         $('#raw_area_2').css('display', '');
115                     } else if (operation == "modify_doc1_2") {
116                         var strRaw = '{"count": 99}';
117                         $('#raw').val(strRaw);
118                         $('#raw_area').css('display', '');
119                     }
120                 });
121 
122             });
123 
124         </script>
125 
126         </body>
127         </html>


    3) 修改 src/main/java/com/example/controller/IndexController.java 文件

  1         package com.example.controller;
  2 
  3         import java.io.IOException;
  4         import java.util.Map;
  5         import java.util.HashMap;
  6 
  7         import org.springframework.beans.factory.annotation.Autowired;
  8         import org.springframework.stereotype.Controller;
  9         import org.springframework.web.bind.annotation.RequestMapping;
 10         import org.springframework.web.bind.annotation.ResponseBody;
 11         import org.springframework.web.bind.annotation.RequestParam;
 12 
 13         import org.elasticsearch.ElasticsearchStatusException;
 14         import org.elasticsearch.common.xcontent.XContentType;
 15         import org.elasticsearch.common.settings.Settings;
 16         import org.elasticsearch.client.RestHighLevelClient;
 17         import org.elasticsearch.client.RequestOptions;
 18         import org.elasticsearch.client.indices.CreateIndexRequest;
 19         import org.elasticsearch.client.indices.CreateIndexResponse;
 20         import org.elasticsearch.client.indices.GetIndexRequest;
 21         import org.elasticsearch.client.indices.GetIndexResponse;
 22 
 23         import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
 24         import org.elasticsearch.action.support.master.AcknowledgedResponse;
 25         import org.elasticsearch.action.index.IndexRequest;
 26         import org.elasticsearch.action.index.IndexResponse;
 27         import org.elasticsearch.action.get.GetRequest;
 28         import org.elasticsearch.action.get.GetResponse;
 29         import org.elasticsearch.action.bulk.BulkRequest;
 30         import org.elasticsearch.action.bulk.BulkResponse;
 31         import org.elasticsearch.action.update.UpdateRequest;
 32         import org.elasticsearch.action.update.UpdateResponse;
 33         import org.elasticsearch.action.delete.DeleteRequest;
 34         import org.elasticsearch.action.delete.DeleteResponse;
 35 
 36         import org.elasticsearch.action.search.SearchRequest;
 37         import org.elasticsearch.action.search.SearchResponse;
 38         import org.elasticsearch.index.query.QueryBuilders;
 39         import org.elasticsearch.search.builder.SearchSourceBuilder;
 40         import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
 41         import org.elasticsearch.search.SearchHit;
 42 
 43         @Controller
 44         public class IndexController {
 45 
 46             @Autowired
 47             private RestHighLevelClient restHighLevelClient;
 48 
 49             @ResponseBody
 50             @RequestMapping("/test")
 51             public String test() {
 52                 return "Test Page";
 53             }
 54 
 55             @RequestMapping("/client")
 56             public String client() {
 57                 return "client";
 58             }
 59 
 60             @ResponseBody
 61             @RequestMapping("/operation")
 62             public Map<String, String> operationPost(@RequestParam String operation,
 63                                                     @RequestParam String raw, @RequestParam String raw2) {
 64 
 65                 Map<String, String> map = new HashMap();
 66                 if ("".equals(operation)) {
 67                     map.put("ret", "ERROR");
 68                     map.put("description", "Operation is empty");
 69                 } else {
 70 
 71                     try {
 72 
 73                         if ("create_springboot".equals(operation)) {
 74 
 75                             CreateIndexRequest request = new CreateIndexRequest("springboot");
 76                             CreateIndexResponse response = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
 77 
 78                             //System.out.println(response);
 79                             map.put("ret", "OK");
 80                             map.put("description", "create_springboot -> " + response.index());
 81 
 82                         } else if ("get_springboot".equals(operation)) {
 83 
 84                             GetIndexRequest request = new GetIndexRequest("springboot");
 85                             GetIndexResponse response = restHighLevelClient.indices().get(request, RequestOptions.DEFAULT);
 86 
 87                             //System.out.println(response);
 88                             map.put("ret", "OK");
 89                             map.put("description", "get_springboot -> " + response.getSettings().toString());
 90 
 91                         } else if ("delete_springboot".equals(operation)) {
 92 
 93                             DeleteIndexRequest request = new DeleteIndexRequest("springboot");
 94                             AcknowledgedResponse response = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
 95 
 96                             //System.out.println(response);
 97                             map.put("ret", "OK");
 98                             map.put("description", "delete_springboot -> " + response.toString());
 99 
100                         } else if ("create_springboot_settings".equals(operation)) {
101 
102                             CreateIndexRequest request = new CreateIndexRequest("springboot");
103                             request.settings(raw, XContentType.JSON);
104                             CreateIndexResponse response = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
105 
106                             System.out.println(response);
107                             map.put("ret", "OK");
108                             map.put("description", "create_springboot_settings -> " + response.index());
109 
110                         } else if ("get_springboot_settings".equals(operation)) {
111 
112                             GetIndexRequest request = new GetIndexRequest("springboot");
113                             GetIndexResponse response = restHighLevelClient.indices().get(request, RequestOptions.DEFAULT);
114 
115                             System.out.println(response);
116                             map.put("ret", "OK");
117                             map.put("description", "get_springboot_settings -> settings: " + response.getSettings()
118                                             + ", mapping: " + response.getMappings());
119 
120                         } else if ("create_doc1_auto".equals(operation)) {
121 
122                             IndexRequest indexRequest = new IndexRequest();
123                             indexRequest.index("springboot");
124                             indexRequest.type("doc1");
125                             indexRequest.source(raw, XContentType.JSON);
126                             IndexResponse response = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
127 
128                             System.out.println(response);
129                             map.put("ret", "OK");
130                             map.put("description", "create_doc1_auto -> id = " + response.getId() + " (" + raw + ")");
131 
132                         } else if ("create_doc1_2".equals(operation)) {
133 
134                             IndexRequest indexRequest = new IndexRequest();
135                             indexRequest.index("springboot");
136                             indexRequest.type("doc1");
137                             indexRequest.id("2");
138                             indexRequest.source(raw, XContentType.JSON);
139                             IndexResponse response = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
140 
141                             System.out.println(response);
142                             map.put("ret", "OK");
143                             map.put("description", "create_doc1_2 -> id = " + response.getId() + " (" + raw + ")");
144 
145                         } else if ("create_doc1_batch".equals(operation)) {
146 
147                             BulkRequest bulkRequest = new BulkRequest("springboot", "doc1");
148 
149                             IndexRequest indexRequest1 = new IndexRequest();
150                             indexRequest1.source(raw, XContentType.JSON);
151 
152                             IndexRequest indexRequest2 = new IndexRequest();
153                             indexRequest2.source(raw2, XContentType.JSON);
154 
155                             bulkRequest.add(indexRequest1);
156                             bulkRequest.add(indexRequest2);
157 
158                             BulkResponse response = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
159 
160                             System.out.println(response);
161                             map.put("ret", "OK");
162                             map.put("description", "create_doc1_batch -> " + response.status());
163 
164                         } else if ("get_doc1_2".equals(operation)) {
165 
166                             GetRequest getRequest = new GetRequest();
167                             getRequest.index("springboot");
168                             getRequest.type("doc1");
169                             getRequest.id("2");
170                             getRequest.fetchSourceContext(new FetchSourceContext(true));
171                             GetResponse response = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
172 
173                             System.out.println(response);
174                             map.put("ret", "OK");
175                             map.put("description", "get_doc1_2 -> " + response.getSourceAsString());
176 
177                         } else if ("modify_doc1_2".equals(operation)) {
178 
179                             UpdateRequest updateRequest = new UpdateRequest();
180                             updateRequest.index("springboot");
181                             updateRequest.type("doc1");
182                             updateRequest.id("2");
183 
184                             updateRequest.doc(raw, XContentType.JSON);
185                             UpdateResponse response = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
186 
187                             System.out.println(response);
188                             map.put("ret", "OK");
189                             map.put("description", "modify_doc1_2 -> " + response.status());
190 
191                         } else if ("delete_doc1_2".equals(operation)) {
192 
193                             DeleteRequest deleteRequest = new DeleteRequest();
194                             deleteRequest.index("springboot");
195                             deleteRequest.type("doc1");
196                             deleteRequest.id("2");
197                             DeleteResponse response = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
198 
199                             System.out.println(response);
200                             map.put("ret", "OK");
201                             map.put("description", "delete_doc1_2 -> " + response.status());
202 
203                         } else if ("query_springboot_docs".equals(operation)) {
204 
205                             SearchRequest searchRequest = new SearchRequest("springboot");
206 
207                             SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
208                             sourceBuilder.query(QueryBuilders.matchAllQuery());
209                             searchRequest.source(sourceBuilder);
210                             SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
211 
212                             System.out.println(response);
213 
214                             String ret = response.status().toString();
215                             if ("OK".equals(ret)) {
216                                 ret = "";
217                                 for (SearchHit hit : response.getHits()) {
218                                     if (ret.isEmpty()) {
219                                         ret = hit.getSourceAsString();
220                                     } else {
221                                         ret += " | " + hit.getSourceAsString();
222                                     }
223                                 }
224                             }
225 
226                             map.put("ret", "OK");
227                             map.put("description", "query_springboot_docs -> " + ret);
228 
229                         } else if ("term_query_springboot_docs".equals(operation)) {
230 
231                             SearchRequest searchRequest = new SearchRequest("springboot");
232 
233                             SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
234                             sourceBuilder.query(QueryBuilders.termQuery("name.keyword","Elastic Search"));
235                             searchRequest.source(sourceBuilder);
236                             SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
237 
238                             System.out.println(response);
239 
240                             String ret = response.status().toString();
241                             if ("OK".equals(ret)) {
242                                 ret = "";
243                                 for (SearchHit hit : response.getHits()) {
244                                     if (ret.isEmpty()) {
245                                         ret = hit.getSourceAsString();
246                                     } else {
247                                         ret += " | " + hit.getSourceAsString();
248                                     }
249                                 }
250                             }
251 
252                             map.put("ret", "OK");
253                             map.put("description", "term_query_springboot_docs -> " + ret);
254 
255                         } else if ("match_query_springboot_docs".equals(operation)) {
256 
257                             SearchRequest searchRequest = new SearchRequest("springboot");
258 
259                             SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
260                             sourceBuilder.query(QueryBuilders.matchQuery("name","Elastic Search"));
261                             searchRequest.source(sourceBuilder);
262                             SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
263 
264                             System.out.println(response);
265 
266                             String ret = response.status().toString();
267                             if ("OK".equals(ret)) {
268                                 ret = "";
269                                 for (SearchHit hit : response.getHits()) {
270                                     if (ret.isEmpty()) {
271                                         ret = hit.getSourceAsString();
272                                     } else {
273                                         ret += " | " + hit.getSourceAsString();
274                                     }
275                                 }
276                             }
277 
278                             map.put("ret", "OK");
279                             map.put("description", "match_query_springboot_docs -> " + ret);
280 
281                         } else {
282                             map.put("ret", "ERROR");
283                             map.put("description", "Invalid operation");
284                         }
285 
286                     } catch (ElasticsearchStatusException e) {
287                         map.put("ret", "ERROR");
288                         map.put("description", e.getMessage());
289                     } catch (IOException e) {
290                         map.put("ret", "ERROR");
291                         map.put("description", e.getMessage());
292                     }
293 
294                 }
295 
296                 return map;
297             }
298 
299         }

    确保 ElasticSearch 服务已正常运行,运行 SpringBoot 项目,浏览器访问 http://localhost:9090/client。


标签:map,20,Springboot,org,elasticsearch,import,ElasticSearch,response,springboot
From: https://www.cnblogs.com/tkuang/p/16953691.html

相关文章