ElasticSearch实战之项目搜索高亮

news2024/9/23 2:29:14

在这里插入图片描述

文章目录

  • 1. 前情配置
  • 2、数据操作
    • 2.1 操作API
    • 2.2 数据入库
  • 3. 高亮搜索
    • 3.1 方法封装
    • 3.2 高亮搜索

1. 前情配置


为满足ElasticSearch可在项目中实现搜索高亮,我们需要先做一些前情配置

  1. 导入ElasticSearch依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
  1. 修改propertise配置
server.port=9090
spring.thymeleaf.cache=false
# 保证url可以输入中文,防止乱码
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true
  1. 构建一个搜索类对象,这里假设我们存在一个搜索对象为Content,其中我们要进行查询的字段是title
@AllArgsConstructor
@NoArgsConstructor
@Data
@Component
public class Content {
    private String title;
    private String img;
    private String price;
}

同时,假设我们拥有List<Content>数据集合,至此,我们做好了所有的前情准备


2、数据操作


2.1 操作API


我们拥有List<Content>数据集合,我们要将其插入到es

步骤分为三步:判断索引是否存在 -> 索引不存在则创建索引 -> 索引存在则插入文档

则数据操作的API分为三个,我们一一实现

API(1):判断索引是否存在

public boolean existIndex(String indexName) throws IOException {
    GetIndexRequest request = new GetIndexRequest(indexName);
    boolean isExists = client.indices().exists(request, RequestOptions.DEFAULT);
    return isExists;
}

API(2):创建索引

这里的indexName利用jd_goods传入,即我们创建的索引名称为jd_goods

public boolean createIndex(String indexName) throws IOException {
    CreateIndexRequest request = new CreateIndexRequest(indexName);
    CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
    return response.isAcknowledged();
}

API(3):批量插入数据

这里的indexName利用jd_goods传入,即我们将的List<Content>数据插入到jd_goods

public boolean bulkAddDoc(String indexName, List<Content> listContent) throws IOException {
    //判断是否存在索引
    if (indexService.existIndex()){
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("10s");
        //存入数据
        for (Content content : listContent) {
          bulkRequest.add(new IndexRequest(indexName)
          .source(JSON.toJSONString(content), XContentType.JSON));
        }
        //执行请求
        BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        //不失败表示插入成功
        return !bulkResponse.hasFailures();
    }
    return false;
}

2.2 数据入库


整合上述方法,我们可以将List<Content>存入es

public boolean parseContent(String indexName,List<Content> list) throws IOException {
    //1. 某个获取数据的方法
    List<Content> list = function();
    //2. 判断索引是否存在,并且插入数据
    if (!indexService.existIndex(String indexName)){
        indexService.createIndex(String indexName);
    }
    //3. 插入数据
    return docService.bulkAddDoc(String indexName,list);
}

再次查看es,数据已经被插入

在这里插入图片描述

3. 高亮搜索


3.1 方法封装


封装用于搜索的方法,这里指定利用term搜索

//param搜索字段名称 searchWord搜索关键字,from和size用于分页
public List<Map<String, Object>> searchDoc(String indexName, String param, String searchWord, Integer from, Integer size) throws IOException {
    //构建搜索类
    SearchSourceBuilder searchBuilder = new SearchSourceBuilder();
    //匹配查询
    TermQueryBuilder termQuery = QueryBuilders.termQuery(param, searchWord);
    //设置超时
    searchBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

    //高亮
    HighlightBuilder highlightBuilder = new HighlightBuilder();
    //设置高亮的字段
    highlightBuilder.field(param);
    //多个高亮显示
    highlightBuilder.requireFieldMatch(false);
    highlightBuilder.preTags("<span style='color:red'>");
    highlightBuilder.postTags("</span>");
    searchBuilder.highlighter(highlightBuilder);

    //分页
    if (from <= 0){
        from = 0;
    }
    if (size != 0){
        searchBuilder.from(from);
        searchBuilder.size(size);
    }

    //封装搜索
    searchBuilder.query(termQuery);
    //创建查询请求,并将搜索类放入
    SearchRequest request = new SearchRequest(indexName).source(searchBuilder);
    //客户端查询请求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    //解析结果,第一次getHits()返回了全部的数据,包括版本信息等
    //第二次getHits()返回了数据中的查询对象
    //getSourceAsMap()表示将查询对象转化为map集合,其中键就是属性,值就是属性对应的值
    ArrayList<Map<String, Object>> list = new ArrayList<>();
    for(SearchHit hit:response.getHits().getHits()){
        //使用新的高亮字段,覆盖旧字段
        Map<String, Object> sourceAsMap = hit.getSourceAsMap();
        //获取全部的高亮字段
        Map<String, HighlightField> highlightFields = hit.getHighlightFields();
        HighlightField title = highlightFields.get(param);
        //开始替换,将旧的title值替换为高亮的值
        if (title != null){
            Text[] fragments = title.getFragments();
            StringBuilder newTitle = new StringBuilder();
            for (Text text:fragments){
                newTitle.append(text);
            }
            sourceAsMap.put(param,newTitle);
        }
        //再次添加进去
        list.add(sourceAsMap);
    }
    return list;
}

整合上述方法,假设我们在jd_goods中搜索title字段

public List<Map<String, Object>> searchContent(String indexName, String keyword,Integer from,Integer size) throws IOException {
    return docService.searchDoc("jd_goods","title",keyword,from,size);
}

3.2 高亮搜索


绑定浏览器地址,尝试查询

@GetMapping("/search/{keyword}/{from}/{size}")
public List<Map<String, Object>> searchContent(@PathVariable("keyword") String keyword,
@PathVariable("from") Integer from,@PathVariable("size") Integer size) throws IOException {
    return contentService.searchContent(keyword,from,size);
}

假设我们需要搜索jd_goods中搜索title字段包含java的字段,同时从第1条数据开始获取,获取的数据大小为20

访问浏览器,关键字已经被设置高亮,只需要传递到前端即可

在这里插入图片描述

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

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

相关文章

怎么设置启用远程桌面? 如何让外网电脑远程本地内网?

如何远程控制电脑&#xff1f;最简单实用的方案是开启电脑系统自带的远程桌面功能&#xff0c;如果涉及跨网、内外网互通&#xff0c;可以同时用快解析内网映射外网。下面是方案的具体实施步骤&#xff0c;供大家参考。 怎么打开设置启用远程桌面&#xff1f; 1.在目标需要远…

【详细讲解CentOS常用的命令】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

android 创建module

文章目的&#xff1a; 快速创建module并使用 创建步骤&#xff1a; 1 创建module 2 修改module下的build.gradle文件 3 修改清单文件中MainActivity属性&#xff0c;否则APP会因为有多个启动界面而崩溃 4 在主项目build.gradle引用该object Module 至此&#xff0c;可在APP中…

排序(五)——非比较排序+排序总结

1.非比较排序 我们前面讲的排序算法都是通过比较大小来进行排序的&#xff0c;他们都是比较排序。 像基数排序、计数排序和桶排序等都不是通过比较大小来排序的&#xff0c;是非比较排序&#xff0c;在这里我们讲一下其中的计数排序和基数排序&#xff0c;而桶排序实现起来太…

在k8s 中部署有状态服务MongoDB高可用集群详解(附带镜像)

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Kubernetes航线图&#xff1a;从船长到K8s掌舵者》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、前言 1、k8s简介 2、MongoDB介绍 3、为什么要…

网络爬虫软件学习

1 什么是爬虫软件 爬虫软件&#xff0c;也称为网络爬虫或网络蜘蛛&#xff0c;是一种自动抓取万维网信息的程序或脚本。它基于一定的规则&#xff0c;自动地访问网页并抓取需要的信息。爬虫软件可以应用于大规模数据采集和分析&#xff0c;广泛应用于舆情监测、品牌竞争分析、…

【 书生·浦语大模型实战营】作业(五):LMDeploy 量化部署

【 书生浦语大模型实战营】作业&#xff08;五&#xff09;&#xff1a;LMDeploy 量化部署 &#x1f389;AI学习星球推荐&#xff1a; GoAI的学习社区 知识星球是一个致力于提供《机器学习 | 深度学习 | CV | NLP | 大模型 | 多模态 | AIGC 》各个最新AI方向综述、论文等成体系…

Vue2之组件通信(爆肝)

大家有什么想看的可以在评论区留言&#xff0c;我尽量满足&#xff0c;感谢大家&#xff01; 组件通信是vue中一个非常重要的内容&#xff0c;我们需要掌握好组件通信&#xff0c;那么让我为大家介绍几种组件通信的方式吧&#xff01; 一、props 这是父传子的方式&#xff0…

FFmpeg合并音视频文件操作备忘(mac版)

利用NDM嗅探插件从B站下载下来的文件是音视频分开的&#xff0c;用剪辑软件合并时发现导出时文件都特别大&#xff0c;于是使用FFmpeg处理 环境&#xff1a; MBP M1芯片版 系统 macOS Sonama 14.4.1 操作步骤&#xff1a; 一、官方下载链接&#xff1a;https://evermeet.cx/…

MySQL 锁机制全面解析

目录 1. MySQL的锁类型1.1 全局锁1.2 表锁1.3 行锁1.4 共享锁&#xff08;读锁&#xff09;1.5 排它锁&#xff08;写锁&#xff09;1.6 死锁 2 乐观锁和悲观锁2.1 乐观锁2.2 悲观锁 3 意向锁4 间隙锁5 临键锁6. 事务隔离级别对锁的影响6.1 读未提交&#xff08;Read Uncommitt…

npm内部机制与核心原理

npm 的核心目标&#xff1a; Bring the best of open source to you, your team and your company. npm 最重要的任务是安装和维护开源库。 npm 安装机制与背后思想 npm 的安装机制非常值得探究。Ruby 的 Gem&#xff0c;Python的pip都是全局安装机制&#xff0c;但是npm的安装…

️️️Vue3+Element-Plus二次封装一个可定制化的table组件

前言 为什么需要二次封装 开发后台管理系统,会接触到很多表格和表单,一但表格表单多起来,仅仅只需要一小部分改变&#xff0c;都需要在中重写一大堆代码,许多重复逻辑,我们可以把重复逻辑抽离出来二次封装一个组件 使用,减少在开发中需要编写的代码。 为什么需要定制化 每个…

【AI工具之Prezo如何自动生成PPT操作步骤】

先说优缺点&#xff1a; 最大的优点就是免费&#xff08;但说实话功能和体验方面很弱&#xff09;支持中文提问&#xff08;最好用英文&#xff09;&#xff0c;智能生成图文&#xff08;但是只能生成英文内容&#xff09;可以AI生成图片&#xff0c;图片很精美酷炫&#xff0…

数据可视化(四):Pandas技术的高级操作案例,豆瓣电影数据也能轻松分析!

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

(八)Pandas窗口数据与数据读写 学习简要笔记 #Python #CDA学习打卡

一. 窗口数据(Window Functions) Pandas提供了窗口函数(Window Functions)用于在数据上执行滑动窗口操作&#xff0c;可以对数据进行滚动计算、滑动统计等操作。需要注意的是&#xff0c;在使用窗口函数时&#xff0c;需要根据实际需求选择合适的窗口大小和窗口函数&#xff0…

硬件设备杂记——12G SDI及 AES67/EBU

常见的 SDI线缆规格&#xff0c;HD-SDI又被称为1.5G-SDI&#xff0c;具体参数以秋叶原的参数为例 AES67/EBU 目前音频网络标准主要集中在OSI网络体系的第二层和第三层。 第二层音频标准的弊端在于构建音频网络时需要专用的交换机&#xff0c;无法利用现有的以太网络&#xff0c…

布局香港之零售中小企篇 | 传承之味,迈向数字化经营的时代

随着内地与香港两地经贸合作日渐紧密&#xff0c;越来越多内地消费品牌将目光投向香港这片充满机遇的热土&#xff0c;纷纷入驻香港市场。「北店南下」蔚然成风&#xff0c;其中不乏已在内地市场深耕多年的传统老字号。数字化经营时代&#xff0c;老字号焕新刻不容缓&#xff0…

QoS流量整形

流量整形是一种带宽技术形式&#xff0c;它延迟某些类型的网络数据包的流动&#xff0c;以确保更高优先级应用程序的网络性能&#xff0c;它主要涉及调整数据传输速率&#xff0c;以确保网络资源以最佳容量得到利用。流量整形的目的是防止网络拥塞并提高网络的整体性能&#xf…

【Leetcode每日一题】 分治 - 排序数组(难度⭐⭐)(60)

1. 题目解析 题目链接&#xff1a;912. 排序数组 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 算法思路&#xff1a; 快速排序作为一种经典的排序算法&#xff0c;其核心思想在于通过“分而治之”的策略&#xff…

C++:深入理解operator new/operator delete

动态内存管理 1.语法层面1.基本语法注意点 2.new/delete和malloc/free的区别3.operator new和operator delete函数&#xff08;底层重点&#xff09;1.operator new/delete原理2.图解1.new/new[]2.delete/delete[] 3.new[n]和delete[] 4.定位new1.定义2.使用格式 1.语法层面 1…