java中的ElasticSearch搜索引擎介绍。

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     }

 

 
posted @ 2018-09-29 17:43  hao踏雪无痕  阅读(9518)  评论(0编辑  收藏  举报