es的高亮查詢


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);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM