elasticsearch分词,排序,分页,高亮简单示例

news2024/11/25 1:05:01

目录

  • 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/588010.html

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

相关文章

SUSE系统上安装HANA

一:安装SUSE操作系统 1.1 准备安装镜像 SLE-15-SP1-安装程序-DVD-x86_64-GM-DVD1 SLE-15-SP1-软件包-x86_64-GM-DVD1 SAP HANA安装文件 IMDB_SERVER20_032_0-80002031.SAR 1.2 引导系统 1.3 选择要安装的产品 SUSE Linux Enterprise Server for SAP Applications 15 SP…

Stable Diffusion教程(5) - 文生图教程

配套视频教程&#xff1a; https://v.douyin.com/UyHNfYG/ 文生图界面标注如下 1 提示词和反向提示词 提示词内输入的东西就是你想要画的东西&#xff0c;反向提示词内输入的就是你不想要画的东西 提示框内只能输入英文&#xff0c;所有符号都要使用英文半角&#xff0c;词语…

企业级信息系统开发讲课笔记4.5 掌握Spring Boot多环境配置

文章目录 零、学习目标一、项目进行多环境配置的必要性二、使用Profile文件进行多环境配置&#xff08;一&#xff09;创建Spring Boot项目&#xff08;二&#xff09;创建多环境配置文件1、全局配置文件改名2、模拟开发环境3、模拟测试环境4、模拟生产环境 &#xff08;三&…

Unity基础 音频组件以及音频播放

在游戏开发中&#xff0c;声音是一个重要的环节。Unity中的声音组件可以帮助开发者轻松地控制游戏中音频的播放、音量、循环等属性&#xff0c;从而实现更好的游戏体验。本文将详细介绍Unity声音组件的相关概念和技术&#xff0c;以及其在游戏、影视等领域的广泛应用和发展前景…

银行联行号-联行号api接口-联行号数据源

接口地址&#xff1a; https://登录后显示/api/180/348(支持:http/https) 数据源&#xff1a;https://www.wapi.cn/source/8.html 网站地址&#xff1a;https://www.wapi.cn 返回格式&#xff1a;json,xml 请求方式&#xff1a;GET,POST 请求说明&#xff1a; 银行联行号-联行…

数据集:T-Drive(北京出租车轨迹数据)

1 数据来源 T-Drive trajectory data sample - Microsoft Research 2 数据介绍 数据集包含了2008年2月2日至2月8日期间在北京市内的10,357辆出租车的GPS轨迹。总共包含约1500万个GPS点&#xff0c;轨迹总里程达到了900万公里。 图1显示了两个连续点之间的时间间隔和距离间隔…

Apache 配置和应用

目录 构建虚拟 Web 主机 Options指令解释 Options指令常用选项 AllowOverride指令解释&#xff1a; 地址限制策略&#xff1a; httpd服务支持的虚拟主机类型包括以下三种: 基于域名的虚拟主机 1&#xff0e;为虚拟主机提供域名解析 2.为虚拟主机准备网页文档 3.添加虚拟…

【服务器】springboot实现HTTP服务监听

文章目录 前言1. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 2. 内网穿透2.1 安装配置cpolar内网穿透2.1.1 windows系统2.1.2 linux系统 2.2 创建隧道映射本地端口2.3 测试公网地址 3. 固定公网地址3.1 保留一个二级子域名3.2 配置二级子域名3.2 测试使用固定公网地址…

Mysql 异常,“Cause: com.mysql.cj.jdbc.exceptions.MySQLTimeoutException”

Cause: com.mysql.cj.jdbc.exceptions.MySQLTimeoutException: Statement cancelled due to timeout or client request 简言&#xff1a;这种异常从字面翻译过来&#xff1a;mysql 请求链接超时&#xff0c;具体超时是什么原因导致的&#xff0c;可以根据情况分析下。 异常详…

【黄啊码】PHP商城中的积分任务系统实现

大家好&#xff0c;我是黄啊码&#xff0c;前几天有位小伙伴问我&#xff0c;商城中的任务系统是怎么实现的&#xff1f; 积分作为一种营销手段&#xff0c;被广泛运用于线上/线下的产品中&#xff0c;以此来增加用户对于产品的粘性。比如天猫积分可以用来兑换商品&#xff0c…

uni-app通过vue.config.js在项目中配置跨域代理

其实这个 如果你用nginx去配肯定再好不过 不过 一般大家也都不想把开发环境弄那么复杂 最好还是在项目中配置 那么 我们选择项目跟目录右键 选择 使用命令行窗口打开所在目录 在新弹出的命令行中引入依赖 npm install http-proxy-middleware --save-dev然后我们的依赖就进来…

【通信接口】CAN总线协议

目录 一、什么是CAN 1、CAN 的概念 2、节点构成&#xff08;CAN 总线通信模型&#xff09; 3、差分信号&#xff08;电平特性&#xff09; 4、CAN 总线的特点 二、CAN 总线协议的通信过程 1、发送过程 2、接收过程 3、概括 三、CAN 通信帧的分类 一、什么是CAN 1、C…

易基因:全基因组ChIP-seq分析揭示细菌转录因子PhoB的基因内结合位点|mBio

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 细菌编码许多转录因子&#xff08;transcription factor&#xff0c;TF&#xff09;&#xff0c;这些转录因子通过与启动子周围的DNA结合并调控RNA聚合酶&#xff08;RNAP&#xff09;全…

微服务架构打造的供应链系统、采购配送系统,支持SaaS模式

一、开源项目简介 haohan-scm 介绍 基于pig微服务架构打造 供应链系统&#xff0c;采购配送系统。为客户提供仓储管理、订单管理、打单、货源采购、分拣、配送等系统功能。 二、开源协议 使用AGPL-3.0开源协议 三、界面展示 系统截图 四、功能概述 基于pig微服务架构打…

电脑重装系统需要多长的时间

电脑重装系统是一个涉及多个步骤和因素的过程&#xff0c;所需的时间会因个体差异和系统配置而异。本文将解析电脑重装系统所需的时间&#xff0c;并提供一些因素和建议&#xff0c;帮助您对整个过程有一个准确的预期。 工具/原料&#xff1a; 系统版本&#xff1a;windows8系…

c语言的预处理和编译

预处理 文件包含 当预处理器发现#include指令时&#xff0c;会查看后面的文件名并把文件的内容包含到当前文件中 两种写法 尖括号&#xff1a;引用的是编译器的库路径里面的头文件。 双引号&#xff1a;引用的是程序目录中相对路径中的头文件&#xff0c;如果找不到再去上面…

【redis基础】事务|管道|发布订阅

大家好~这里是redis系列文章之《【redis基础】事务|管道|发布订阅》上一篇文章&#xff1a;redis持久化【RDBAOF】持久化双雄_努力努力再努力mlx的博客-CSDN博客 目录 事务 概念 作用 数据库事务vs redis事务 常用指令 情况1&#xff1a;正常执行 情况2&#xff1a;放弃…

微信小程序开发实践入门教程

随着微信小程序的火爆&#xff0c;越来越多的人开始关注微信小程序开发并加入开发大军中&#xff0c;而很多人对于如何开发微信小程序&#xff0c;并没有很好的思路和方法。因此&#xff0c;为了方便大家在学习、实践和应用的过程中能够少走弯路&#xff0c;本文将通过一篇关于…

IE11离线安装包ie离线升级ie11离线安装ie11补丁

首先下载ie11离线安装包与补丁文件&#xff1a; 下载地址&#xff08;我的资源里有&#xff09;&#xff1a; &#xff08;如不着急可私信直接要安装包补丁包&#xff0c;我若看到及时回复你&#xff09; 1、 下载补丁文件和IE11安装程序&#xff08;这里以32位系统为例&…

uni-app 金额格式化

普通过滤器(filter)在当前页面定义&#xff0c;复制红色代码即可 <template> <view> <text >{{balance|money}}</text> </view> </template> <script> export default{ data(){ return{ …