java中的ElasticSearch搜索引擎介绍。总结

不点 阅读:3552 2021-05-20 12:41:46 评论:0

ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

安装

以windows操作系统和ES0.19.7版本为例:
①下载elasticsearch-6.4.1.zip
②直接解压至某目录,设置该目录为ES_HOME 环境变量
③安装JDK,并设置JAVA_HOME环境变量
④在windows下,运行 %ES_HOME%\bin\elasticsearch.bat即可运行

安装插件

以head插件为例:
联网时,直接运行%ES_HOME%\bin\plugin --install mobz/elasticsearch-head
不联网时,下载elasticsearch-head的zipball的master包,然后运行%ES_HOME%\bin\plugin --url file:///[path-to-downloadfile] --install head,其中[path-to-downloadfile]是下载后master包的绝对路径
安装完成,重启服务,在浏览器打开 http://localhost:9200/_plugin/head/ 即可

 ES工作原理

当ElasticSearch的节点启动后,它会利用多播(multicast)(或者单播,如果用户更改了配置)寻找集群中的其它节点,并与之建立连接。这个过程如下图所示: 
这里写图片描述

官方代码
1
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder( 2 new HttpHost("localhost", 9200, "http"))); 3 SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 4 searchSourceBuilder.query(QueryBuilders.matchAllQuery()); 5 searchSourceBuilder.aggregation(AggregationBuilders.terms("top_10_states").field("state").size(10)); 6 SearchRequest searchRequest = new SearchRequest(); 7 searchRequest.indices("social-*"); 8 searchRequest.source(searchSourceBuilder); 9 SearchResponse searchResponse = client.search(searchRequest);

创建索引

 1 /** 
 2      * 创建索引 
 3      * 
 4      * @param index 
 5      * @return 
 6      */ 
 7     public boolean createIndex(String index) { 
 8         if (!isIndexExist(index)) { 
 9             logger.info("index is not exits!"); 
10         } 
11         CreateIndexResponse indexresponse = client.admin().indices().prepareCreate(index).execute().actionGet(); 
12         logger.info("success to create index " + indexresponse.isAcknowledged()); 
13  
14         return indexresponse.isAcknowledged(); 
15     }

删除索引

 1 /** 
 2      * 删除索引 
 3      * 
 4      * @param index 
 5      * @return 
 6      */ 
 7     public boolean deleteIndex(String index) { 
 8         if (!isIndexExist(index)) { 
 9             logger.info("index is not exits!"); 
10         } 
11         DeleteIndexResponse dResponse = client.admin().indices().prepareDelete(index).execute().actionGet(); 
12         if (dResponse.isAcknowledged()) { 
13             logger.info("delete index " + index + "  successfully!"); 
14         } else { 
15             logger.info("fail to delete index " + index); 
16         } 
17         return dResponse.isAcknowledged(); 
18     }

判断

 1 /** 
 2      * 判断索引是否存在 
 3      * 
 4      * @param index 
 5      * @return 
 6      */ 
 7     public boolean isIndexExist(String index) { 
 8         IndicesExistsResponse inExistsResponse = client.admin().indices().exists(new IndicesExistsRequest(index)).actionGet(); 
 9         if (inExistsResponse.isExists()) { 
10             logger.info("index [" + index + "] is exist!"); 
11         } else { 
12             logger.info("index [" + index + "] is not exist!"); 
13         } 
14         return inExistsResponse.isExists(); 
15     }
  1  /** 
  2      * 通过ID获取数据 
  3      * 
  4      * @param index  索引,类似数据库 
  5      * @param type   类型,类似表 
  6      * @param id     数据ID 
  7      * @param fields 需要显示的字段,逗号分隔(缺省为全部字段) 
  8      * @return 
  9      */ 
 10     public Map<String, Object> searchDataById(String index, String type, String id, String fields) { 
 11         GetRequestBuilder getRequestBuilder = client.prepareGet(index, type, id); 
 12         if (StringUtils.isNotEmpty(fields)) { 
 13             getRequestBuilder.setFetchSource(fields.split(","), null); 
 14         } 
 15         GetResponse getResponse =  getRequestBuilder.execute().actionGet(); 
 16         return getResponse.getSource(); 
 17     } 
 18  
 19     /** 
 20      * 使用分词查询 
 21      * 
 22      * @param index    索引名称 
 23      * @param type     类型名称,可传入多个type逗号分隔 
 24      * @param fields   需要显示的字段,逗号分隔(缺省为全部字段) 
 25      * @param matchStr 过滤条件(xxx=111,aaa=222) 
 26      * @return 
 27      */ 
 28     public List<Map<String, Object>> searchListData(String index, String type, String fields, String matchStr) { 
 29         return searchListData(index, type, 0, 0, null, fields, null, false, null, matchStr); 
 30     } 
 31  
 32     /** 
 33      * 使用分词查询 
 34      * 
 35      * @param index       索引名称 
 36      * @param type        类型名称,可传入多个type逗号分隔 
 37      * @param fields      需要显示的字段,逗号分隔(缺省为全部字段) 
 38      * @param sortField   排序字段 
 39      * @param matchPhrase true 使用,短语精准匹配 
 40      * @param matchStr    过滤条件(xxx=111,aaa=222) 
 41      * @return 
 42      */ 
 43     public List<Map<String, Object>> searchListData(String index, String type, String fields, String sortField, boolean matchPhrase, String matchStr) { 
 44         return searchListData(index, type, 0, 0, null, fields, sortField, matchPhrase, null, matchStr); 
 45     } 
 46  
 47  
 48     /** 
 49      * 使用分词查询 
 50      * 
 51      * @param index          索引名称 
 52      * @param type           类型名称,可传入多个type逗号分隔 
 53      * @param size           文档大小限制 
 54      * @param fields         需要显示的字段,逗号分隔(缺省为全部字段) 
 55      * @param sortField      排序字段 
 56      * @param matchPhrase    true 使用,短语精准匹配 
 57      * @param highlightField 高亮字段 
 58      * @param matchStr       过滤条件(xxx=111,aaa=222) 
 59      * @return 
 60      */ 
 61     public List<Map<String, Object>> searchListData(String index, String type, Integer size, String fields, String sortField, boolean matchPhrase, String highlightField, String matchStr) { 
 62         return searchListData(index, type, 0, 0, size, fields, sortField, matchPhrase, highlightField, matchStr); 
 63     } 
 64  
 65  
 66     /** 
 67      * 使用分词查询 
 68      * 
 69      * @param index          索引名称 
 70      * @param type           类型名称,可传入多个type逗号分隔 
 71      * @param startTime      开始时间 
 72      * @param endTime        结束时间 
 73      * @param size           文档大小限制 
 74      * @param fields         需要显示的字段,逗号分隔(缺省为全部字段) 
 75      * @param sortField      排序字段 
 76      * @param matchPhrase    true 使用,短语精准匹配 
 77      * @param highlightField 高亮字段 
 78      * @param matchStr       过滤条件(xxx=111,aaa=222) 
 79      * @return 
 80      */ 
 81     public List<Map<String, Object>> searchListData(String index, String type, long startTime, long endTime, Integer size, String fields, String sortField, boolean matchPhrase, String highlightField, String matchStr) { 
 82         SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index); 
 83         if (StringUtils.isNotEmpty(type)) { 
 84             searchRequestBuilder.setTypes(type.split(",")); 
 85         } 
 86         BoolQueryBuilder boolQuery = QueryBuilders.boolQuery(); 
 87          
 88         if (startTime > 0 && endTime > 0) { 
 89             boolQuery.must(QueryBuilders.rangeQuery("processTime") 
 90                     .format("epoch_millis") 
 91                     .from(startTime) 
 92                     .to(endTime) 
 93                     .includeLower(true) 
 94                     .includeUpper(true)); 
 95         } 
 96  
 97         //搜索的的字段 
 98         if (StringUtils.isNotEmpty(matchStr)) { 
 99             for (String s : matchStr.split(",")) { 
100                 String[] ss = s.split("="); 
101                 if (ss.length > 1) { 
102                     if (matchPhrase == Boolean.TRUE) { 
103                         boolQuery.must(QueryBuilders.matchPhraseQuery(s.split("=")[0], s.split("=")[1])); 
104                     } else { 
105                         boolQuery.must(QueryBuilders.matchQuery(s.split("=")[0], s.split("=")[1])); 
106                     } 
107                 } 
108             } 
109         } 
110  
111         // 高亮(xxx=111,aaa=222) 
112         if (StringUtils.isNotEmpty(highlightField)) { 
113             HighlightBuilder highlightBuilder = new HighlightBuilder(); 
114  
115             //highlightBuilder.preTags("<span style='color:red' >");//设置前缀 
116             //highlightBuilder.postTags("</span>");//设置后缀 
117  
118             // 设置高亮字段 
119             highlightBuilder.field(highlightField); 
120             searchRequestBuilder.highlighter(highlightBuilder); 
121         } 
122          
123         searchRequestBuilder.setQuery(boolQuery); 
124          
125         if (StringUtils.isNotEmpty(fields)) { 
126             searchRequestBuilder.setFetchSource(fields.split(","), null); 
127         } 
128         searchRequestBuilder.setFetchSource(true); 
129  
130         if (StringUtils.isNotEmpty(sortField)) { 
131             searchRequestBuilder.addSort(sortField, SortOrder.DESC); 
132         } 
133  
134         if (size != null && size > 0) { 
135             searchRequestBuilder.setSize(size); 
136         } 
137  
138         //打印的内容 可以在 Elasticsearch head 和 Kibana  上执行查询 
139 //        logger.info("\n{}", searchRequestBuilder); 
140  
141         SearchResponse searchResponse = searchRequestBuilder.execute().actionGet(); 
142  
143         long totalHits = searchResponse.getHits().totalHits; 
144         long length = searchResponse.getHits().getHits().length; 
145  
146 //        logger.info("共查询到[{}]条数据,处理数据条数[{}]", totalHits, length); 
147  
148         if (searchResponse.status().getStatus() == 200) { 
149             // 解析对象 
150             return setSearchResponse(searchResponse, highlightField); 
151         } 
152         return null; 
153     } 
154  
155     /** 
156      * 使用分词查询,并分页 
157      * 
158      * @param index          索引名称 
159      * @param type           类型名称,可传入多个type逗号分隔 
160      * @param currentPage    当前页 
161      * @param pageSize       每页显示条数 
162      * @param startTime      开始时间 
163      * @param endTime        结束时间 
164      * @param fields         需要显示的字段,逗号分隔(缺省为全部字段) 
165      * @param sortField      排序字段 
166      * @param matchPhrase    true 使用,短语精准匹配 
167      * @param highlightField 高亮字段 
168      * @param matchStr       过滤条件(xxx=111,aaa=222) 
169      * @return 
170      */ 
171     public EsPage searchDataPage(String index, String type, int currentPage, int pageSize, long startTime, long endTime, String fields, String sortField, boolean matchPhrase, String highlightField, String matchStr) { 
172         SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index); 
173         if (StringUtils.isNotEmpty(type)) { 
174             searchRequestBuilder.setTypes(type.split(",")); 
175         } 
176         searchRequestBuilder.setSearchType(SearchType.QUERY_THEN_FETCH); 
177  
178         // 需要显示的字段,逗号分隔(缺省为全部字段) 
179         if (StringUtils.isNotEmpty(fields)) { 
180             searchRequestBuilder.setFetchSource(fields.split(","), null); 
181         } 
182  
183         //排序字段 
184         if (StringUtils.isNotEmpty(sortField)) { 
185             searchRequestBuilder.addSort(sortField, SortOrder.DESC); 
186         } 
187  
188         BoolQueryBuilder boolQuery = QueryBuilders.boolQuery(); 
189  
190         if (startTime > 0 && endTime > 0) { 
191             boolQuery.must(QueryBuilders.rangeQuery("@timestamp") 
192                     .format("epoch_millis") 
193                     .from(startTime) 
194                     .to(endTime) 
195                     .includeLower(true) 
196                     .includeUpper(true)); 
197         } 
198  
199         // 查询字段 
200         if (StringUtils.isNotEmpty(matchStr)) { 
201             for (String s : matchStr.split(",")) { 
202                 String[] ss = s.split("="); 
203                 if (ss.length > 1) { 
204                     if (matchPhrase == Boolean.TRUE) { 
205                         boolQuery.must(QueryBuilders.matchPhraseQuery(s.split("=")[0], s.split("=")[1])); 
206                     } else { 
207                         boolQuery.must(QueryBuilders.matchQuery(s.split("=")[0], s.split("=")[1])); 
208                     } 
209                 } 
210             } 
211         } 
212  
213         // 高亮(xxx=111,aaa=222) 
214         if (StringUtils.isNotEmpty(highlightField)) { 
215             HighlightBuilder highlightBuilder = new HighlightBuilder(); 
216  
217             //highlightBuilder.preTags("<span style='color:red' >");//设置前缀 
218             //highlightBuilder.postTags("</span>");//设置后缀 
219  
220             // 设置高亮字段 
221             highlightBuilder.field(highlightField); 
222             searchRequestBuilder.highlighter(highlightBuilder); 
223         } 
224  
225         searchRequestBuilder.setQuery(QueryBuilders.matchAllQuery()); 
226         searchRequestBuilder.setQuery(boolQuery); 
227  
228         // 分页应用 
229         searchRequestBuilder.setFrom(currentPage).setSize(pageSize); 
230  
231         // 设置是否按查询匹配度排序 
232         searchRequestBuilder.setExplain(true); 
233  
234         //打印的内容 可以在 Elasticsearch head 和 Kibana  上执行查询 
235 //        logger.info("\n{}", searchRequestBuilder); 
236  
237         // 执行搜索,返回搜索响应信息 
238         SearchResponse searchResponse = searchRequestBuilder.execute().actionGet(); 
239  
240         long totalHits = searchResponse.getHits().totalHits; 
241         long length = searchResponse.getHits().getHits().length; 
242  
243 //        logger.debug("共查询到[{}]条数据,处理数据条数[{}]", totalHits, length); 
244  
245         if (searchResponse.status().getStatus() == 200) { 
246             // 解析对象 
247             List<Map<String, Object>> sourceList = setSearchResponse(searchResponse, highlightField); 
248  
249             return new EsPage(currentPage, pageSize, (int) totalHits, sourceList); 
250         } 
251         return null; 
252     } 
253  
254     /** 
255      * 高亮结果集 特殊处理 
256      * 
257      * @param searchResponse 
258      * @param highlightField 
259      */ 
260     private List<Map<String, Object>> setSearchResponse(SearchResponse searchResponse, String highlightField) { 
261         List<Map<String, Object>> sourceList = new ArrayList<Map<String, Object>>(); 
262         StringBuffer stringBuffer = new StringBuffer(); 
263  
264         for (SearchHit searchHit : searchResponse.getHits().getHits()) { 
265             searchHit.getSource().put("id", searchHit.getId()); 
266  
267             if (StringUtils.isNotEmpty(highlightField)) { 
268  
269                 System.out.println("遍历 高亮结果集,覆盖 正常结果集" + searchHit.getSource()); 
270                 Text[] text = searchHit.getHighlightFields().get(highlightField).getFragments(); 
271  
272                 if (text != null) { 
273                     for (Text str : text) { 
274                         stringBuffer.append(str.string()); 
275                     } 
276                     //遍历 高亮结果集,覆盖 正常结果集 
277                     searchHit.getSource().put(highlightField, stringBuffer.toString()); 
278                 } 
279             } 
280             sourceList.add(searchHit.getSource()); 
281         } 
282         return sourceList; 
283     }
 

声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

全民解析

全民解析

关注我们