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);
原文地址:https://www.cnblogs.com/liujinqq7/p/12693708.html