spring boot使用elasticsearch分词,排序,分页,高亮简单示例

目录

  • 1. 创建ES实体
  • 2. 创建查询实体
  • 3. 查询方法实现
    • 3.1 核心代码
    • 3.2 构建查询条件
      • 3.2.1 关键词分词
    • 3.3 高亮处理
  • 4.完整查询代码展示

记,写一个简单的es分词demo,es版本6.8.12

如果使用es7有些方法可能会有所改变,请参考7的文档

es安装教程:http://t.csdn.cn/BSh12

1. 创建ES实体

怎么简单怎么来

@Data
@Document(indexName = "goods")
public class GoodsEsItem implements Serializable {
    //主键
    @Id
    private Long id;

    @Field(type = FieldType.Text, analyzer = "ik_max_word")  //商品名
    private String name;
    
    private String category;


    @Field(type = FieldType.Date)
    private Date create_time;

    @Field(type = FieldType.Date)
    private Date update_time;

}

2. 创建查询实体

@Data
public class GoodsQueryVo {
    /**
     * 关键字
     */
    private String keyword;

    /**
     * 分类
     */
    private String category;


    /**
     * 当前页
     */
    private Integer current;

    /**
     * 每页大小
     */
    private Integer pageSize;

    /**
     * 排序字段
     */
    private String sfield;

    /**
     * 排序格式asc,desc
     */
    private String sm;
}

3. 查询方法实现

3.1 核心代码

@Override
public Map<String, Object> searchByKeyword(GoodsQueryVo goodsQueryVo) {
    	//构建查询条件
        NativeSearchQueryBuilder queryBuilder = queryBuilder(goodsQueryVo);

        //添加高亮域
        HighlightBuilder.Field field = new HighlightBuilder.
                Field("name").                      //指定的高亮域
                preTags("<span style=\"color:red\">").   //前缀
                postTags("</span>").                      //后缀
                fragmentSize(100);
        queryBuilder.withHighlightFields(field);
        //执行搜索。HighlightResultMapper处理高亮文本
        AggregatedPage<PblGoodsEsItem> results = elasticsearchRestTemplate.queryForPage(queryBuilder.build(), PblGoodsEsItem.class, new HighlightResultMapper());
        //结果集
        Map<String, Object> resultMap = new HashMap<String, Object>();
        resultMap.put("list", results.getContent());
        resultMap.put("total", results.getTotalElements());
        return resultMap;
}

3.2 构建查询条件

商品名称加了 @Field(type = FieldType.Text, analyzer = “ik_max_word”) 会自动分词

private NativeSearchQueryBuilder queryBuilder(GoodsQueryVo goodsQueryVo) {
    //关键字分词
    EsIkResult esIkResult = keywordToken(goodsQueryVo);
    List<String> tokens = esIkResult.getTokens().stream().map(EsIkResult.token::getToken).collect(Collectors.toList());
    //QueryBuilder构建
    NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();

    //多条件组合查询对象
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

    //关键字条件should构建or条件,must构建and条件
    BoolQueryBuilder keywordQuery = QueryBuilders.boolQuery();
    tokens.forEach(e -> {
        keywordQuery.should(QueryBuilders.termQuery("name", e));
    });
	
    //分类条件
    if (!StringUtils.isEmpty(goodsQueryVo.getCategory())) {
        boolQuery.must(QueryBuilders.termQuery("category",goodsQueryVo.getCategory()));
    }
    //这里的关系为(keyword1 or keyword2) and category
    boolQuery.must(keywordQuery);
    //分页
    queryBuilder.withPageable(PageRequest.of(currentPage(goodsQueryVo), goodsQueryVo.getPageSize()));
    //排序
    String sfield = goodsQueryVo.getSfield();
    String sm = goodsQueryVo.getSm();
    if (!StringUtils.isEmpty(sfield) && !StringUtils.isEmpty(sm)) {
        queryBuilder.withSort(
            SortBuilders.fieldSort(sfield)   //排序域
            .order(SortOrder.valueOf(sm)));  //排序方式
    }
    return queryBuilder.withQuery(boolQuery);
}

分页处理

public int currentPage(GoodsQueryVo goodsQueryVo) {
    try {
        Object currentPage = goodsQueryVo.getCurrent();
        return Integer.parseInt(currentPage.toString()) > 0 ? Integer.parseInt(currentPage.toString()) - 1 : 0;
    } catch (Exception e) {
        return 0;
    }
}

3.2.1 关键词分词

当输入衣服鞋子的时候会将关键字分为衣服,鞋子去查询

@Data
public class EsIkResult {

    private List<token> tokens;

    @Data
    public static class token{
        private String token;

        @JSONField(name = "start_offset")
        private Integer startOffset;

        @JSONField(name = "end_offset")
        private Integer endOffset;

        private String type;

        private Integer position;
    }
}

HttpUtil是自己封装的http请求类,可以根据自己的方式去发出请求

private EsIkResult keywordToken(GoodsQueryVo goodsQueryVo) {
    HashMap<String, Object> params = new HashMap<>();
    params.put("analyzer", "ik_max_word");
    params.put("text", goodsQueryVo.getKeyword());
    return HttpUtil.post("http://localhost:9200/_analyze?pretty", params, EsIkResult.class);
}

3.3 高亮处理

高亮处理mapper,处理高亮数据,复制用即可,不需要记

public class HighlightResultMapper extends DefaultResultMapper {
    /***
     * 处理结果集
     */
    @Override
    public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
        //所有数据
        for (SearchHit hit : response.getHits()) {
            //当前单条数据
            Map<String, Object> sourceMap = hit.getSourceAsMap();
            //高亮数据
            for (Map.Entry<String, HighlightField> entry : hit.getHighlightFields().entrySet()) {
                String key = entry.getKey();
                if (sourceMap.containsKey(key)) {
                    Text[] fragments = entry.getValue().getFragments();
                    sourceMap.put(key, transTextArrayToString(fragments));
                }
            }
            hit.sourceRef(new ByteBufferReference(ByteBuffer.wrap(JSONObject.toJSONString(sourceMap).getBytes())));
        }
        return super.mapResults(response, clazz, pageable);
    }

    /***
     * 拼接数据碎片
     */
    private String transTextArrayToString(Text[] fragments) {
        if (null == fragments) {
            return "";
        }
        StringBuffer buffer = new StringBuffer();
        for (Text fragment : fragments) {
            buffer.append(fragment.string());
        }
        return buffer.toString();
    }
}

添加高亮,在上面·searchByKeyword方法有写到

此处会将name字段含有关键字的文本替换成<span style=“color:red”> 包含,前端用html回显即可

示例,搜索衣服

image-20230530120004406

//添加高亮域
HighlightBuilder.Field field = new HighlightBuilder.
        Field("name").                      //指定的高亮域
        preTags("<span style=\"color:red\">").   //前缀
        postTags("</span>").                      //后缀
        fragmentSize(100);
queryBuilder.withHighlightFields(field);
//执行搜索。HighlightResultMapper处理高亮文本
AggregatedPage<PblGoodsEsItem> results = elasticsearchRestTemplate.queryForPage(queryBuilder.build(), PblGoodsEsItem.class, new HighlightResultMapper());

4.完整查询代码展示

ps:

高亮处理代码上方已给出,此处只给出搜索代码

HttpUtil是自己封装的http请求类,可以根据自己的方式去发出请求

@Service
public class GoodsEsServiceImpl implements GoodsEsService {

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Override
    public Map<String, Object> searchByKeyword(GoodsQueryVo goodsQueryVo) {
        //构建查询条件
        NativeSearchQueryBuilder queryBuilder = queryBuilder(goodsQueryVo);

        //添加高亮域
        HighlightBuilder.Field field = new HighlightBuilder.
                Field("name").                      //指定的高亮域
                preTags("<span style=\"color:red\">").   //前缀
                postTags("</span>").                      //后缀
                fragmentSize(100);
        queryBuilder.withHighlightFields(field);
        //执行搜索。HighlightResultMapper处理高亮文本
        AggregatedPage<PblGoodsEsItem> results = elasticsearchRestTemplate.queryForPage(queryBuilder.build(), PblGoodsEsItem.class, new HighlightResultMapper());
        //结果集
        Map<String, Object> resultMap = new HashMap<String, Object>();
        resultMap.put("list", results.getContent());
        resultMap.put("total", results.getTotalElements());
        return resultMap;
    }

    private NativeSearchQueryBuilder queryBuilder(GoodsQueryVo goodsQueryVo) {
        //关键字分词
        EsIkResult esIkResult = keywordToken(goodsQueryVo);
        List<String> tokens = esIkResult.getTokens().stream().map(EsIkResult.token::getToken).collect(Collectors.toList());
        //QueryBuilder构建
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();

        //多条件组合查询对象
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        //关键字条件should构建or条件,must构建and条件
        BoolQueryBuilder keywordQuery = QueryBuilders.boolQuery();
        tokens.forEach(e -> {
            keywordQuery.should(QueryBuilders.termQuery("name", e));
        });

        //分类条件
        if (!StringUtils.isEmpty(goodsQueryVo.getCategory())) {
            boolQuery.must(QueryBuilders.termQuery("category",goodsQueryVo.getCategory()));
        }
        //这里的关系为(keyword1 or keyword2) and category
        boolQuery.must(keywordQuery);
        //分页
        queryBuilder.withPageable(PageRequest.of(currentPage(goodsQueryVo), goodsQueryVo.getPageSize()));
        //排序
        String sfield = goodsQueryVo.getSfield();
        String sm = goodsQueryVo.getSm();
        if (!StringUtils.isEmpty(sfield) && !StringUtils.isEmpty(sm)) {
            queryBuilder.withSort(
                    SortBuilders.fieldSort(sfield)   //排序域
                            .order(SortOrder.valueOf(sm)));  //排序方式
        }
        return queryBuilder.withQuery(boolQuery);
    }

    public int currentPage(GoodsQueryVo goodsQueryVo) {
        try {
            Object currentPage = goodsQueryVo.getCurrent();
            return Integer.parseInt(currentPage.toString()) > 0 ? Integer.parseInt(currentPage.toString()) - 1 : 0;
        } catch (Exception e) {
            return 0;
        }
    }

    private EsIkResult keywordToken(GoodsQueryVo goodsQueryVo) {
        HashMap<String, Object> params = new HashMap<>();
        params.put("analyzer", "ik_max_word");
        params.put("text", goodsQueryVo.getKeyword());
        return HttpUtil.post("http://localhost:9200/_analyze?pretty", params, EsIkResult.class);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/25060.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

隔离驱动芯片SLMi332兼容光耦隔离驱动器时的注意事项

数明深力科SLMi33x系列SLMi332是一款兼容光耦带DESAT保护功能的IGBT/SiC隔离驱动器。内置快速去饱和(DESAT) 故障检测功能、米勒钳位功能、漏极开路故障反馈、软关断功能以及可选择的自恢复模式&#xff0c;兼容光耦隔离驱动器。 SLMi33x系列SLMi332的DESAT阈值为6.5V&#xf…

大数据---聚类分析概述及聚类评估

聚类概述: 什么是聚类&#xff1f; 是把数据对象集合按照相似性划分成多个子集的过程。每个子集是一个簇&#xff08;cluster&#xff09;&#xff0c;分类的最终效果&#xff1a;使得簇中的对象彼此相似&#xff0c;但与其他簇中的对象相异。聚类是无监督学习&#xff0c;因…

缓存被穿透了怎么办?

首先来了解几个概念&#xff1a; 缓存穿透&#xff1a;大量请求根本不存在的key 缓存雪崩&#xff1a;redis中大量key集体过期 缓存击穿&#xff1a;redis中一个热点key过期&#xff08;大量用户访问该热点key&#xff0c;但是热点key过期&#xff09; 穿透解决方案 对空值…

如何有效和快速清理C盘

电脑在运行过程中会产生磁盘碎片&#xff0c;时间一长垃圾文件就会越多。而且我们平常不敢乱清理C盘中的文件&#xff0c;以免因为误删导致系统出现故障&#xff0c;所以垃圾文件才肆意占用系统盘空间。不过我们可以选择系统自带的“磁盘清理”功能“制服”它&#xff0c;给C盘…

带电更换柱上变压器(综合不停电作业法)

一、现场复勘 1.核对工作线路双重名称、杆号及设备双重名称 2.检查杆身质量 3.检查线路装置是否符合带电作业要求 4.检查待更换变压器容量 满足旁路作业要求 5.检查气象条件 作业前进行湿度和风速的测量&#xff0c;风力大于5级或湿度大于80%时&#xff0c;不宜带电作业&…

华为开源自研AI框架昇思MindSpore应用案例:Pix2Pix实现图像转换

目录 一、环境准备1.进入ModelArts官网2.使用CodeLab体验Notebook实例 二、基础原理三、准备环节配置环境文件准备数据数据展示 四、创建网络生成器G结构定义UNet Skip Connection Block基于UNet的生成器 基于PatchGAN的判别器Pix2Pix的生成器和判别器初始化 五、训练六、推理 …

SWAT模型教程

详情点击链接&#xff1a;SWAT模型教程详情点击链接&#xff1a;SWAT模型&#xff08;建模方法、实例应用、高级进阶&#xff09; 一&#xff1a;基于网络资源的SWAT模型快速建模​ 二&#xff1a;基于遥感产品的SWAT模型率定与验证​ 三&#xff1a;基于水文响应单元&#xff…

每日一题——用两个队列实现栈

每日一题 用两个队列实现栈 题目链接 思路 这里主要讲怎么实现出栈StackPop操作做完用两个栈实现队列&#xff0c;我们可能会想当然的认为&#xff0c;这一题也是一个主队列&#xff0c;一个辅助队列&#xff0c;当要出队时&#xff0c;首先判断辅助队列是否为空&#xff0c;…

FineBI6.0基础学习第一课 数据门户

PC端门户使用示例 首先,以管理员身份登录FineBI系统,安装数据门户,安装步骤见官网 新建一个数据门户

C++中的高阶函数:以std::function优雅地实现回调

C中的高阶函数&#xff1a;以std::function优雅地实现回调 1. 简介1.1 C高阶函数的概念1.2 C的std::function的功能及其重要性 2. std::function的使用2.1 std::function的定义和基本使用2.1.1 std::function的定义2.1.2 std::function的基本使用 2.2 std::function接受普通函数…

Python+Yolov5人脸表情特征识别

程序示例精选 PythonYolov5人脸表情特征识别 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<PythonYolov5人脸表情特征识别>>编写代码&#xff0c;代码整洁&#xff0c;规则&am…

Linux环境变量总结

Linux是一个多用户的操作系统。多用户意味着每个用户登录系统后&#xff0c;都有自己专用的运行环境。而这个环境是由一组变量所定义,这组变量被称为环境变量。用户可以对自己的环境变量进行修改以达到对环境的要求。 设置环境变量的方法 对所有用户生效的永久性变量 这类变…

电子科技大学编译原理复习笔记(三):控制结构

目录 前言 重点一览 语句级控制结构 单元级控制结构 四种单元级控制结构 本章小结 前言 本复习笔记基于张老师的课堂PPT&#xff0c;供自己期末复习与学弟学妹参考用。 重点一览 语句级控制结构 定义&#xff1a;用来构造各种语句执行顺序的机制 传统三种语句级控制结…

【问题记录】解决vite多页应用路由改用history之后本地刷新404问题

当前包的版本信息&#xff1a; "vue": "^2.7.14", "vue-router": "^3.6.5" "vite": "^3.0.7", 首先&#xff0c;修改路由模式 首先&#xff0c;将之前多页项目中的某个页面路由模式改用 history &#xff0c;…

【异常捕获】

异常捕获 异常概念处理错误方式 异常处理举例栈展开异常规范异常继承层次优缺点 异常 概念 异常时程序可能检测到的&#xff0c;运行时不正常的情况&#xff0c;如存储空间耗尽&#xff0c;数组越界等&#xff0c;可以预见可能发生在什么地方但不知道在什么时候发生的错误。 …

mysql倒库操作遇到的问题

背景&#xff1a;本地windows 10安装了mysql数据库后&#xff0c;需要把远程库的表结构和数据全部导入进来。 操作&#xff1a;导出数据库&#xff0c;导入数据库。 第一步&#xff1a;导出数据库 使用dump命令即可。 登陆mysql数据库 mysql -hhost --default-character-s…

海汽集团:业财共享服务中心建设推进集团数字治理

随着大数据时代的到来&#xff0c;数字化、信息化的财务管理方式应运而生。建立财务共享服务中心&#xff0c;走向业财一体化&#xff0c;已成为企业财务管理转型的必然趋势。 海汽集团作为全国唯一一家具有全省性客运网络的道路运输企业、海南道路运输业头部企业&#xff0c;…

3. 自然语言处理NLP:具体用途(近义词类比词;情感分类;机器翻译)

一、求近义词和类比词 1. 近义词 方法一&#xff1a;在嵌入模型后&#xff0c;可以根据两个词向量的余弦相似度表示词与词之间在语义上的相似度。 方法二&#xff1a;KNN&#xff08;K近邻&#xff09; 2. 类比词 使用预训练词向量求词与词之间的类比关系。eg&#xff1a;man&a…

​Lambda表达式详解​-初遇者-很细

目录 Lambda简介 对接口的要求 Lambda 基础语法 Lambda 语法简化 Lambda 表达式常用示例 lambda 表达式引用方法 构造方法的引用 lambda 表达式创建线程 遍历集合 删除集合中的某个元素 集合内元素的排序 Lambda 表达式中的闭包问题 Lambda简介 Lambda 表达式是 JD…

元宇宙应用领域-运动

元宇宙作为互联网的下一个阶段&#xff0c;目前已经发展成为一个多领域的“平行宇宙”&#xff0c;其中就包括体育。从体育的角度来看&#xff0c;元宇宙将是一个集运动、娱乐、社交、生活、学习于一体的“平行宇宙”&#xff0c;可以让人们在元宇宙中进行更好的运动&#xff0…