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

news2024/11/23 2:33:23

目录

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PMP-识别相关方的重要性

一、为什么要识别相关方 每个项目都有相关方&#xff0c;他们会受项目的积极或消极影响&#xff0c;或者能对项目施加积极或消极的影响。有些相关方影响项目工作或成果的能力有限&#xff0c;而有些相关方可能对项目及其期望成果有重大影响。项目经理和团队正确识别并合理引导所…

Apache的日志分割

一、日志分割的作用 我们知道当服务安装完成以后&#xff0c;都会在相关服务下有一个logs文件里面有着访问日志和错误日志。访问日志可以帮我们记录访问者的信息&#xff0c;错误日志一般在服务搭建&#xff0c;服务配置&#xff0c;启动时能够快速寻找错误原因的日志&#xf…

堆的应用(堆排序、TOP - K问题)

前言 &#x1f34e; 时间复杂度&#xff1a; &#x1f95d; 堆排序的最坏时间复杂度为 &#xff1a;O(n*lg(n)) &#x1f95d; TOP - K问题的最坏时间复杂度为&#xff1a;O(n*lg(k)) &#x1f341;前面我们学习了二叉树、以及堆的结构&#xff0c;也用顺序表的结构成功的把堆的…

【uni-app】使用外部组件不显示报错组件未找到解决方案

文章目录 前言一、问题描述二、温馨提示总结 前言 大家好&#xff0c;今天和大家分享一下uni-app使用外部组件不显示报错的一个解决方案&#xff0c;希望能够帮助到大家。 一、问题描述 我在使用uni-app在开发项目时引入了一个外部的组件库&#xff0c;刚开始引入的时候还是…

【复习笔记】FreeRTOS(二)创建和删除任务

本文是FreeRTOS复习笔记的第二节&#xff0c;创建和删除任务&#xff0c;使用的开发板是stm32f407VET6&#xff0c;创建两个任务&#xff0c;task1负责闪烁LED&#xff0c;task2负责按键控制&#xff0c;当按键按下时task1停止执行&#xff0c;任务的状态显示到TFT显示屏和串口…

【数据库系统及应用】— 日志、故障恢复、事务、并发控制、调度、检查点

日志文件是用于记录__________。 A、数据操作 B、程序运行过程 C、程序执行结果 D、对数据的所有更新操作 下列说法正确的是__________。 A、事务故障可以通过运行日志进行恢复 B、介质故障只需将备份恢复到系统中即可实现正确性 C、检查点是指检查发生故障并进行恢复的时刻点…

MySQL 对日期使用 DATE_FORMAT()函数

文章目录 DATE_FORMAT()函数显示今天是星期几只显示年月显示当前时间的分钟数和秒数 DATE_FORMAT()函数 前面使用日期时间函数&#xff0c;获取到的要么是 yyyy-mm-dd 形式的日期&#xff0c;要么是 hh:MM:ss 形式的时间&#xff0c;或者是 yyyy-mm-dd hh:mm:ss 形式的日期及时…

论文解读 | ICRA2022:用深度贝叶斯算法来估计ICP的协方差

原创 | 文 BFT机器人 01 研究背景 在点云处理中&#xff0c;ICP算法是一种常用的点云配准方法&#xff0c;通过将两个或多个点云对齐&#xff0c;可以进行后续的建模、识别和跟踪等处理。 然而&#xff0c;在ICP算法中&#xff0c;协方差估计起着非常重要的作用&#xff0c;它…

网络安全基础免杀

1. 会话提升的几种方式2. armitage的熟悉3. handler生成监听器的方法4. 防止会话假死5. 控制台设置编码6. upx加壳7. msfvenom木马payload持久化8. msfvenom木马编码 正文 免杀1 1. 会话提升的几种方式 python -c "import pty;pty.spawn(/bin/bash);" 会话提升 se…

linuxOps基础_linux文件打包压缩与解压缩

linux打包压缩概念 默认情况下&#xff0c;Linux的压缩概念一次只能压缩一个文件。针对多文件或文件夹无法进行直接压缩。所以需要提前对多个文件或文件夹进行打包&#xff0c;这样才可以进行压缩操作。 打包 1.txt 5MB 2.txt 10MB 3.txt 15MB1.txt 2.txt 3.txt 打包…

为kong网关添加key-auth插件实现安全认证

官方指导文档&#xff1a;https://docs.konghq.com/gateway/latest/get-started/key-authentication/ 一、新建一个用户 这里我们新建一个usernameluka的用户 [rootmin ~]# curl -i -X POST http://localhost:8001/consumers/ \ > --data usernameluka HTTP/1.1 201 Cr…

JavaEE HTTP状态码 HTTP数据报的构造

HTTP状态码HTTP数据报的构造 文章目录 JavaEE & HTTP状态码 & HTTP数据报的构造1. HTTP状态码1.1 200 - OK1.2 404 - Not Found1.3 403 - Forbidden1.4 500 - Internal Server Error1.5 504 - Gateway Timeout1.6 302/301 重定向 2. 构造HTTP请求2.1 浏览器搜索栏输入u…

聚焦2023北京安博会,超高清安防应用将成潮流

&#xff08;1&#xff09;2023北京安博会 中国安全防范产品行业协会主办并承办的第十六届&#xff08;2023&#xff09;中国国际社会公共安全产品博览会&#xff08;Security China 2023&#xff09;&#xff0c;将于2023年6月7&#xff5e;10日在北京首钢会展中心开幕。安博…

面试阿里测开岗失败后,被面试官在朋友圈吐槽了......

前一阵子有个徒弟向我诉苦&#xff0c;说自己在参加某大厂测试面试的时候被面试官怼得哑口无言&#xff0c;场面让他一度十分尴尬 印象最深的就是下面几个问题&#xff1a; 根据你以前的工作经验和学习到的测试技术&#xff0c;说说你对质量保证的理解&#xff1f; 非关系型…

Jenkins+JMeter实现自动化,性能压测玩转CICD!

目录 前言&#xff1a; 准备工作 编写Jenkinsfile 编写JMeter脚本 编写 Dockerfile 总结 前言&#xff1a; 性能压测是应用程序开发中不可或缺的一环。它通过模拟应用程序在真实环境下的负载情况&#xff0c;从而检测系统在高负载下的性能表现。而随着依托云架构部署业务的不…

2022年长三角高校数学建模竞赛B题齿轮箱故障诊断解题全过程文档及程序

2022年长三角高校数学建模竞赛 B题 齿轮箱故障诊断 原题再现&#xff1a; 齿轮箱是用于增加输出扭矩或改变电机速度的机械装置&#xff0c;被广泛应用于如汽车、输送机、风机等机械设备中。它由两个或多个齿轮组成&#xff0c;其中一个齿轮由电机驱动。电机的轴连接到齿轮箱的…

大数据 Ranger2.1.0 适配 Kafka3.4.0

Ranger2.1.0 适配 Kafka3.4.0 官方说明POM代码说明 根据官方说明Kafka3.0以上版本将会被替换权限认证方式&#xff0c;包括 类和方法 的变换&#xff0c;所以需要对ranger中继承 kafka 的实现中&#xff0c;修改相应的逻辑 官方说明 Kafka3.0以上版本将会被替换权限认证方式&a…

vue项目瘦身

如图 项目中node_modules包已占用十几G&#xff0c;我也是发现我的磁盘空间缩小的超级快&#xff0c;因为好几个项目&#xff0c;甚至有的项目包已经占了50多G&#xff0c;这都得益于上一个刚走了的laji npm install -g depcheck 一旦安装了depCheck&#xff0c;您可以在命令行…

通过 Github workflows CI/CD 自动化部署 Github Pages hugo 免费博客

通过 Github workflows CI/CD 自动化部署 Github Pages hugo 免费博客 文章博客地址&#xff1a;https://blog.taoluyuan.com/posts/github-workflows/ Github Workflows 介绍 GitHub Actions 介绍 GitHub 文档&#xff1a;https://docs.github.com/zh/actions/learn-githu…

相机的畸变矫正与opencv代码说明

相机的畸变矫正与opencv代码说明 简介鱼眼模型的畸变校正针孔模型的畸变校正 简介 图像算法中会经常用到摄像机的畸变校正&#xff0c;有必要总结分析OpenCV中畸变校正方法&#xff0c;其中包括普通针孔相机模型和鱼眼相机模型fisheye两种畸变校正方法。普通相机模型畸变校正函…