1.導入配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/data/elasticsearch http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 掃描Dao包,自動創建實例,制定一個es倉庫的包掃描位置 --> <!-- 主要是用spring-data的方式來操作es的增刪改查 --> <!-- 這個包下就是我們聲明的es倉庫的接口 --> <elasticsearch:repositories base-package="com.liujin.cms.dao" /> <!-- es提供了2個端口號:9200和9300 9200:對瀏覽器暴露的端口號 9300:是對java編程需要操作es所暴露的端口號 --> <!-- 指定es的IP地址和端口號 通過瀏覽器發送restful請求,就能夠實現es的crud--> <elasticsearch:transport-client id="client" cluster-nodes="192.168.26.130:9300" /> <!-- spring data elasticSearcheDao 必須繼承 ElasticsearchTemplate --> <!-- 聲明一個對象,叫elasticsearchTemplate 就是負責es的CRUD的操作 --> <bean id="elasticsearchTemplate" class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate"> <constructor-arg name="client" ref="client"></constructor-arg> </bean> </beans>
2.在所要檢索的實體類下加入注解
//指定了庫名、表名(庫名必須用純小寫,不能有特殊字符)
@Document(indexName = "zhunneng",type = "plan")
public class Plan implements Serializable{
//指定id
@Id
private int id;
//指定name字段的值是否索引,是否存儲 分詞方式 搜索的關鍵字分詞的方式 指定數據類型
@Field(index = true,store = true,analyzer = "ik_max_word",searchAnalyzer = "ik_max_word",type = FieldType.text)
private String name;
private double amount;
@Field(index = true,store = true,analyzer = "ik_max_word",searchAnalyzer = "ik_max_word",type = FieldType.text)
private String manager;
@Field(index = true,store = true,analyzer = "ik_max_word",searchAnalyzer = "ik_max_word",type = FieldType.text)
private String content;
private Dept dept;
3.在dao層下寫入抽象類繼承接口ElasticsearchRepository
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import com.liujin.cms.domain.Plan;
////當你的接口繼承了這個接口之后,就自動具備了crud的功能 1.指定要操作的實體類 2.實體類主鍵類型 public interface PlanRepository extends ElasticsearchRepository<Plan, Integer>{ }
4.導入工具類
/** * Copyright © 2019 公司名. All rights reserved. * * @Title: ESUtils.java * @Prject: chengongjun_cms * @Package: com.chengongjun.chengongjun_cms.utils * @Description: TODO * @author: chj * @date: 2019年7月24日 上午10:14:13 * @version: V1.0 */ package com.liujin.cms.util; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; import org.elasticsearch.search.fetch.subphase.highlight.HighlightField; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.data.elasticsearch.core.SearchResultMapper; import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage; import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl; import org.springframework.data.elasticsearch.core.query.GetQuery; import org.springframework.data.elasticsearch.core.query.IndexQuery; import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.SearchQuery; import com.github.pagehelper.PageInfo; /** * @ClassName: ESUtils * @Description: TODO * @author: * @date: 2019年7月24日 上午10:14:13 */ public class HLUtils { /** * 保存及更新方法 * * @param elasticsearchTemplate * @param id * @param object */ public static void saveObject(ElasticsearchTemplate elasticsearchTemplate, String id, Object object) { // 創建所以對象 IndexQuery query = new IndexQueryBuilder().withId(id).withObject(object).build(); // 建立索引 elasticsearchTemplate.index(query); } /** * 批量刪除 * * @param elasticsearchTemplate * @param clazz * @param ids */ public static void deleteObject(ElasticsearchTemplate elasticsearchTemplate, Class<?> clazz, Integer ids[]) { for (Integer id : ids) { // 建立索引 elasticsearchTemplate.delete(clazz, id + ""); } } /** * * @Title: selectById * @Description: 根據id在es服務啟中查詢對象 * @param elasticsearchTemplate * @param clazz * @param id * @return * @return: Object */ public static Object selectById(ElasticsearchTemplate elasticsearchTemplate, Class<?> clazz, Integer id) { GetQuery query = new GetQuery(); query.setId(id + ""); return elasticsearchTemplate.queryForObject(query, clazz); } //當你的接口繼承了這個接口之后,就自動具備了crud的功能 1.指定要操作的實體類 2.實體類主鍵類型 //public interface UserRespository extends ElasticsearchCrudRepository<User, Integer> //指定了庫名、表名(庫名必須用純小寫,不能有特殊字符) //@Document(indexName = "test_user",type = "user") //指定name字段的值是否索引,是否存儲 分詞方式 搜索的關鍵字分詞的方式 指定數據類型 //@Field(index = true,store = true,analyzer = "ik_smart",searchAnalyzer ="ik_smart",type = FieldType.text ) // 查詢操作 //HLUtils.findByHighLight(elasticsearchTemplate, CompanyAnnualCheck.class, pageNum, pageSize, new String[] {"keywords","companyName"}, "id", key); public static PageInfo<?> findByHighLight(ElasticsearchTemplate elasticsearchTemplate, Class<?> clazz, Integer page, Integer rows, String fieldNames[],String sortField, String value) { AggregatedPage<?> pageInfo = null; PageInfo<?> pi = new PageInfo<>(); // 創建Pageable對象 主鍵的實體類屬性名 final Pageable pageable = PageRequest.of(page - 1, rows, Sort.by(Sort.Direction.ASC, sortField)); //查詢對象 SearchQuery query = null; //查詢條件高亮的構建對象 QueryBuilder queryBuilder = null; if (value != null && !"".equals(value)) { // 高亮拼接的前綴與后綴 String preTags = "<font color=\"red\">"; String postTags = "</font>"; // 定義創建高亮的構建集合對象 HighlightBuilder.Field highlightFields[] = new HighlightBuilder.Field[fieldNames.length]; for (int i = 0; i < fieldNames.length; i++) { // 這個代碼有問題 highlightFields[i] = new HighlightBuilder.Field(fieldNames[i]).preTags(preTags).postTags(postTags); } // 創建queryBuilder對象 queryBuilder = QueryBuilders.multiMatchQuery(value, fieldNames); query = new NativeSearchQueryBuilder().withQuery(queryBuilder).withHighlightFields(highlightFields) .withPageable(pageable).build(); pageInfo = elasticsearchTemplate.queryForPage(query, clazz, new SearchResultMapper() { public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable1) { List<T> content = new ArrayList<T>(); long total = 0l; try { // 查詢結果 SearchHits hits = response.getHits(); if (hits != null) { //獲取總記錄數 total = hits.getTotalHits(); // 獲取結果數組 SearchHit[] searchHits = hits.getHits(); // 判斷結果 if (searchHits != null && searchHits.length > 0) { // 遍歷結果 for (int i = 0; i < searchHits.length; i++) { // 對象值 T entity = clazz.newInstance(); // 獲取具體的結果 SearchHit searchHit = searchHits[i]; // 獲取對象的所有的字段 Field[] fields = clazz.getDeclaredFields(); // 遍歷字段對象 for (int k = 0; k < fields.length; k++) { // 獲取字段對象 Field field = fields[k]; // 暴力反射 field.setAccessible(true); // 字段名稱 String fieldName = field.getName(); if (!fieldName.equals("serialVersionUID")&&!fieldName.equals("user")&&!fieldName.equals("channel")&&!fieldName.equals("category")&&!fieldName.equals("articleType")&&!fieldName.equals("imgList")) { HighlightField highlightField = searchHit.getHighlightFields() .get(fieldName); if (highlightField != null) { // 高亮 處理 拿到 被<font color='red'> </font>結束所包圍的內容部分 String value = highlightField.getFragments()[0].toString(); // 注意一下他是否是 string類型 field.set(entity, value); } else { //獲取某個字段對應的 value值 Object value = searchHit.getSourceAsMap().get(fieldName); // 獲取字段的類型 Class<?> type = field.getType(); if (type == Date.class) { // bug if(value!=null) { field.set(entity, new Date(Long.valueOf(value + ""))); } } else { field.set(entity, value); } } } } content.add(entity); } } } } catch (Exception e) { e.printStackTrace(); } return new AggregatedPageImpl<T>(content, pageable, total); } }); } else { // 沒有查詢條件的的時候,獲取es中的全部數據 分頁獲取 query = new NativeSearchQueryBuilder().withPageable(pageable).build(); pageInfo = elasticsearchTemplate.queryForPage(query, clazz); } int totalCount = (int) pageInfo.getTotalElements(); int pages = totalCount%rows==0?totalCount/rows:totalCount/rows+1; pi.setTotal(pageInfo.getTotalElements()); pi.setPageNum(page); pi.setPageSize(rows); pi.setPrePage(page-1); pi.setLastPage(page+1); pi.setPages(pages); List content = pageInfo.getContent(); pi.setList(content); return pi; } }
5.在controller下調用工具類中的高亮查詢的方法
// 查詢操作 //HLUtils.findByHighLight(elasticsearchTemplate, CompanyAnnualCheck.class, pageNum, pageSize, new String[] {"keywords","companyName"}, "id", key);