最近项目中需要用到搜索引擎,接下去简单的记录下使用过程。
我使用的是springboot框架
-
在pom文件中添加Elasticsearch Maven依赖
<dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>5.6.0</version> </dependency> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>5.5.0</version> </dependency>`
-
添加es 额外文件,java代码同根目录下
例如在我的项目中是这样放的
NamedXcontentProvider.java 具体代码:
package org.elasticsearch.plugins.spi;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import java.util.List;
/**
* Provides named XContent parsers.
*/
public interface NamedXContentProvider {
/**
* @return a list of {@link NamedXContentRegistry.Entry} that this plugin provides.
*/
List<NamedXContentRegistry.Entry> getNamedXContentParsers();
}
-
yml文件中添加es的配置项
elasticsearch: mode: true host: 0.0.0.0 port: 8200 username: admin password: 123456 modename: es_node
-
初始化es客户端
@Configuration public class ElasticsearchConfiguration { @Autowired private Environment environment; @Bean public RestHighLevelClient initData() throws Exception { if (Boolean.valueOf(environment.getProperty("elasticsearch.mode"))) { // 连接信息 String host = environment.getProperty("elasticsearch.host"); String port = environment.getProperty("elasticsearch.port"); String username = environment.getProperty("elasticsearch.username"); String password = environment.getProperty("elasticsearch.password"); String[] hs = host.split(","); String[] ps = port.split(","); HttpHost[] httpHosts = new HttpHost[hs.length]; for (int i = 0; i < hs.length; i++) { httpHosts[i] = new HttpHost(hs[i], Integer.valueOf(ps[i])); } // 连接客户端 final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password)); RestClient restClientBuilder = RestClient.builder(httpHosts) .setMaxRetryTimeoutMillis(5 * 60 * 1000) .setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder .setDefaultCredentialsProvider(credentialsProvider)) .setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() { @Override public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) { requestConfigBuilder.setConnectTimeout(50000); requestConfigBuilder.setSocketTimeout(50000); requestConfigBuilder.setConnectionRequestTimeout(50000); return requestConfigBuilder; } }) .build(); RestHighLevelClient restHighLevelClient = new RestHighLevelClient(restClientBuilder); return restHighLevelClient; } } }
-
es操作类
@Component public class ElasticSearchClient { private Logger logger = LoggerFactory.getLogger(ElasticsearchClient.class); @Autowired private RestHighLevelClient client; /** * 数据添加 * * @param jsonObject 要增加的数据 * @param index 索引,类似数据库 * @param type 类型,类似表 * @param id 数据ID * @return */ public String addData(JSONObject jsonObject, String index, String type, String id) throws IOException { IndexRequest indexRequest = new IndexRequest(index, type, id); indexRequest.source(jsonObject.toJSONString(), XContentType.JSON); IndexResponse indexResponse = null; indexResponse = client.index(indexRequest); long version = indexResponse.getVersion(); return indexResponse.getId(); } /** * 通过ID删除数据 * * @param index 索引,类似数据库 * @param type 类型,类似表 * @param id数据ID */ public void deleteDataByFileCode(String index, String type, String id) throws IOException { DeleteRequest request = new DeleteRequest(index, type, id); DeleteResponse deleteResponse = client.delete(request); } /** * 通过ID 更新数据 * * @param jsonObject 要增加的数据 * @param index 索引,类似数据库 * @param type 类型,类似表 * @param id 数据ID * @return */ public void updateDataByFileCode(JSONObject jsonObject, String index, String type, String id) throws IOException { UpdateRequest updateRequest = new UpdateRequest(index, type, id); updateRequest.doc(jsonObject.toJSONString(), XContentType.JSON); UpdateResponse updateResponse = client.update(updateRequest); } //按唯一标识符,查询 public List<Map<String, Object>> selectListByUniqueTag(String index, String type, QueryBuilder query) throws IOException { SearchRequest searchRequest = new SearchRequest(index); searchRequest.types(type); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(query); searchSourceBuilder.timeout(new TimeValue(5, TimeUnit.SECONDS)); searchRequest.source(searchSourceBuilder); // 执行搜索,返回搜索响应信息 SearchResponse searchResponse = client.search(searchRequest); SearchHit[] hits = searchResponse.getHits().getHits(); List<Map<String, Object>> list = new ArrayList<>(); for (SearchHit searchHit : hits) { Map<String, Object> sourceAsMap = searchHit.getSourceAsMap(); list.add(sourceAsMap); } return list; } //查询一条数据 public SearchHit searchOneData(String index, String type, QueryBuilder query) throws IOException { SearchRequest searchRequest = new SearchRequest(index); searchRequest.types(type); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(query); searchSourceBuilder.timeout(new TimeValue(5, TimeUnit.SECONDS)); searchRequest.source(searchSourceBuilder); // 执行搜索,返回搜索响应信息 SearchResponse searchResponse = client.search(searchRequest); SearchHit[] hits = searchResponse.getHits().getHits(); SearchHit hit = null; if (hits != null && hits.length == 0) { hit = hits[0]; } return hit; } /** * 使用分词查询,并分页 * * @param index 索引名称 * @param type 类型名称,可传入多个type逗号分隔 * @param startPage当前页 * @param pageSize 每页显示条数 * @param query 查询条件 * @param sortField 排序字段 * @param sortOrder 排序方式s * @param highlightField 高亮字段 * @return */ public EsPage searchDataPage(String index, String type, int startPage, int pageSize, QueryBuilder query, String orderBy, Boolean matchOrder, String highlightField, AggregationBuilder aggregationBuilder, String aggName) throws IOException { SearchRequest searchRequest = new SearchRequest(index); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(query); if (pageSize != 0) { searchSourceBuilder.from(startPage); searchSourceBuilder.size(pageSize); } searchSourceBuilder.timeout(new TimeValue(5, TimeUnit.SECONDS)); if (StringUtils.isNotEmpty(type)) { searchRequest.types(type); } // 高亮(xxx=111,aaa=222) if (StringUtils.isNotEmpty(highlightField)) { HighlightBuilder highlightBuilder = new HighlightBuilder(); //设置高亮 String preTags = "<span class='red'>"; String postTags = "</span>"; highlightBuilder.preTags(preTags); highlightBuilder.postTags(postTags); // 设置高亮字段 highlightBuilder.field(highlightField); searchSourceBuilder.highlighter(highlightBuilder); } if (aggregationBuilder != null) { searchSourceBuilder.aggregation(aggregationBuilder); } else { //排序 order(searchSourceBuilder, orderBy, matchOrder); } //打印的内容 可以在 Elasticsearch head 和 Kibana 上执行查询 logger.info("\n{}", searchSourceBuilder); searchRequest.source(searchSourceBuilder); // 执行搜索,返回搜索响应信息 SearchResponse searchResponse = client.search(searchRequest); Aggregations aggregations = searchResponse.getAggregations(); //聚合查询的内容 Terms fileTypeGroup = null; if (aggregations != null && StringUtils.isNotBlank(aggName)) { fileTypeGroup = aggregations.get(aggName); } long totalHits = searchResponse.getHits().getTotalHits(); long length = searchResponse.getHits().getHits().length; logger.debug("共查询到[{}]条数据,处理数据条数[{}]", totalHits, length); if (searchResponse.status().getStatus() == 200) { // 解析对象 List<Map<String, Object>> sourceList = setSearchResponse(searchResponse, highlightField); return new EsPage(startPage, pageSize, (int) totalHits, sourceList, fileTypeGroup); } return null; } /** * 高亮结果集 特殊处理 * * @param searchResponse * @param highlightField */ private List<Map<String, Object>> setSearchResponse(SearchResponse searchResponse, String highlightField) { List<Map<String, Object>> sourceList = new ArrayList<Map<String, Object>>(); for (SearchHit searchHit : searchResponse.getHits().getHits()) { StringBuffer stringBuffer = new StringBuffer(); if (StringUtils.isNotEmpty(highlightField)) { logger.info("遍历 高亮结果集,覆盖 正常结果集" + searchHit.getSourceAsMap()); HighlightField titleField = searchHit.getHighlightFields().get(highlightField); if (titleField == null) { continue; } Text[] text = titleField.getFragments(); if (text != null) { for (Text str : text) { stringBuffer.append(str.string()); } //遍历 高亮结果集,覆盖 正常结果集 searchHit.getSourceAsMap().put(highlightField, stringBuffer.toString()); } } sourceList.add(searchHit.getSourceAsMap()); } return sourceList; } /** * 批量插入数据 * @param index * @param type * @param list */ public int bulkPutIndex(String index, String type, List<BookVO> list) { RestHighLevelClient client = ElasticsearchSingleton.getInstance().getClient(); BulkRequest bulkRequest = new BulkRequest(); int sum = 0; for (BookVO bookVO : list) { IndexRequest indexRequest = new IndexRequest(index, type, bookVO.getFileCode()); indexRequest.source(JSON.toJSONString(bookVO), XContentType.JSON); bulkRequest.add(indexRequest); sum++; } try { client.bulk(bulkRequest); } catch (IOException e) { e.printStackTrace(); } return sum; } }
-
ES 分页器 EsPage.java
public class EsPage { /** * 当前页 */ private int currentPage; /** * 每页显示多少条 */ private int pageSize; /** * 总记录数 */ private int recordCount; /** * 本页的数据列表 */ private List<Map<String, Object>> recordList; /** * 总页数 */ private int pageCount; /** * 页码列表的开始索引(包含) */ private int beginPageIndex; /** * 页码列表的结束索引(包含) */ private int endPageIndex; private Terms terms; /** * 只接受前4个必要的属性,会自动的计算出其他3个属性的值 * * @param currentPage * @param pageSize * @param recordCount * @param recordList */ public EsPage(int currentPage, int pageSize, int recordCount, List<Map<String, Object>> recordList, Terms terms) { this.currentPage = currentPage; this.pageSize = pageSize; this.recordCount = recordCount; this.recordList = recordList; this.terms = terms; // 计算总页码 pageCount = (recordCount + pageSize - 1) / pageSize; // 计算 beginPageIndex 和 endPageIndex // >> 总页数不多于10页,则全部显示 if (pageCount <= 10) { beginPageIndex = 1; endPageIndex = pageCount; } // >> 总页数多于10页,则显示当前页附近的共10个页码 else { // 当前页附近的共10个页码(前4个 + 当前页 + 后5个) beginPageIndex = currentPage - 4; endPageIndex = currentPage + 5; // 当前面的页码不足4个时,则显示前10个页码 if (beginPageIndex < 1) { beginPageIndex = 1; endPageIndex = 10; } // 当后面的页码不足5个时,则显示后10个页码 if (endPageIndex > pageCount) { endPageIndex = pageCount; beginPageIndex = pageCount - 10 + 1; } } } public Terms getTerms() { return terms; } public void setTerms(Terms terms) { this.terms = terms; } public int getCurrentPage() { return currentPage; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getRecordCount() { return recordCount; } public void setRecordCount(int recordCount) { this.recordCount = recordCount; } public List<Map<String, Object>> getRecordList() { return recordList; } public void setRecordList(List<Map<String, Object>> recordList) { this.recordList = recordList; } public int getPageCount() { return pageCount; } public void setPageCount(int pageCount) { this.pageCount = pageCount; } public int getBeginPageIndex() { return beginPageIndex; } public void setBeginPageIndex(int beginPageIndex) { this.beginPageIndex = beginPageIndex; } public int getEndPageIndex() { return endPageIndex; } public void setEndPageIndex(int endPageIndex) { this.endPageIndex = endPageIndex; } }