Elasticsearch使用实战以及代码详解

Elasticsearch 是一个使用 Java 语言编写、遵守 Apache 协议、支持 RESTful 风格的分布式全文搜索和分析引擎,它基于 Lucene 库构建,并提供多种语言的 API。Elasticsearch 可以对任何类型的数据进行索引、查询和聚合分析,无论是文本、数字、地理空间、结构化还是非结构化的。Elasticsearch 的核心功能是搜索,它可以对数据进行分词匹配、相关性评分、高亮显示等操作,返回相关度高的结果列表。Elasticsearch 也可以用作数据分析,它可以对数据进行统计、分类、聚类等操作,返回聚合结果或图表。

本文大纲如下,

应用场景

Elasticsearch 的典型应用场景有以下几种:

  • 全文搜索:Elasticsearch 提供了全文搜索的功能,适用于电商商品搜索、App 搜索、企业内部信息搜索、IT 系统搜索等。例如我们可以为每一个商品作为文档保存进 Elasticsearch,然后使用 Elasticsearch 的查询语言来对文档进行分词匹配、相关性评分、高亮显示等操作,返回相关度高的结果列表。
  • 日志分析:Elasticsearch 可以用来收集、存储和分析海量的日志数据,如项目日志、Nginx log、MySQL Log 等,往往很难从繁杂的日志中获取有价值的信息。Elasticsearch 能够借助 Beats、Logstash 等工具快速对接各种常见的数据源,并通过集成的 Kibana 高效地完成日志的可视化分析,让日志产生价值。
  • 运维监控:Elasticsearch 也可以用来监控和管理 IT 系统的运行状态和性能指标,如 CPU、内存、磁盘、网络等。可以使用 Beats、Logstash 将这些数据实时采集并索引到 Elasticsearch 中,然后通过 Kibana 构建自定义的仪表盘和告警规则,实现实时的运维监控和预警。
  • 数据可视化:Elasticsearch 与 Kibana 的结合提供了强大的数据可视化能力,可以使用 Kibana 来创建各种类型的图表和仪表盘,展示 Elasticsearch 中存储或聚合的数据,如直方图、饼图、地图、时间线等。还可以使用 Kibana 的 Canvas 功能来制作动态的数据展示页面,或者使用 Kibana 的 Lens 功能来进行交互式的数据探索。

商城选择使用 Elasticsearch 作为搜索引擎,负责对商品数据进行索引和检索,选择 Elasticsearch 的原因有以下几点,

  1. Elasticsearch 是一个开源的分布式搜索引擎,基于 Lucene 开发,支持全文检索、结构化检索、地理位置检索等多种类型的检索,功能丰富。
  2. Elasticsearch 本身具有高性能和高可用性的设计,可以通过集群和分片机制实现水平扩展,支持海量数据的存储和处理,适合大规模的商城搜索场景。
  3. Elasticsearch 网上社区活跃,现有互联网上有大量的使用文档和案例,方便入门使用和问题排查。
  4. Elasticsearch 有众多分词器插件,关于中文分词器的使用非常成熟,拿来即用,支持自定义字典等。

waynboot 项目使用的 Elasticsearch 插件

Elasticsearch 的插件非常丰富,我给大家介绍其中 waynboot 项目使用的 Elasticsearch 插件。

IK Analyzer

IK Analyzer 是一个开源的中文分词器,由阿里巴巴集团发布。它采用了细粒度切分和歧义处理等技术,能够较好地处理各种中文文本。IK Analyzer 支持普通模式、搜索模式和拼音模式三种分词方式,并可以根据需要自定义字典。

Pinyin Analyzer

Pinyin Analyzer 插件是一个用于将中文字符转换为拼音的插件,它集成了 NLP 工具(nlp-lang)。该插件包含了分析器:pinyin,分词器:pinyin 和 token-filter:pinyin。该插件还提供了一些可选的参数,可以控制拼音的输出格式,例如是否保留首字母,是否保留全拼,是否保留非中文字符等。

目录结构

在 项目中,给 Elasticsearch 定义了专门的数据访问层 waynboot-data-elastic,该层目录结构如下,

    |-- waynboot-data                    // 数据访问层|   |-- waynboot-data-elastic        // Elasticsearch访问配置模块|       |-- config|       |-- constant|       |-- mananger

包目录说明如下,

  • config:Elasticsearch 相关的配置类,包含 ElasticConfig 连接配置类 以及 ElasticClientConfig 客户端配置相关类,ElasticClientConfig 类可以设置访问密码。
  • constants:Elasticsearch 访问层的相关常量类,这里面定义了商品同步数据的索引名称等信息。
  • mananger:Elasticsearch 访问层的相关操作类,定义了 ElasticDocument 文档操作类,用于操作 Elasticsearch。

代码实战

在项目中,Elasticsearch 主要用于支持首页商品的分词搜索、分页排序等功能。Elasticsearch 版本是 7.0,以下实战讲解都是在 7.0 版本基础上进行。

要使用 Elasticsearch ik 分词器进行中文分词搜索,首先需要安装相应的插件 elasticsearch-analysis-ik,然后在创建索引时指定使用中文分词器作为字段的 analyzer 属性。

在日常对 Elasticsearch 的操作中,我们可以通过 rest api 的方式进行操作。

Elasticsearch rest api 操作

如下我们可以创建一个索引名称为 goods,包含两个属性 title、content。并且 这两个属性都使用 ik 分词器。注意这里我用的 Elasticsearch 提供 Rest api 方式创建索引。

    PUT /goods{"settings": {"index": {"number_of_shards": 1,"number_of_replicas": 0}},"mappings": {"properties": {"title": {"type": "text","analyzer": "ik_max_word"},"content": {"type": "text","analyzer": "ik_max_word"}}}}

创建索引后,就可以向索引中添加两条数据,例如:

    POST /books/_doc/1{"title": "格林童话","content": "这本书介绍了很多童话故事,有白雪公主、狮子王、美人鱼等。"}POST /books/_doc/2{"title": "中国童话故事","content": "这本书介绍了很多中国童话故事。"}

然后我们就可以使用 match 语法来进行中文分词检索,这里我查询 goods 索引中,title 属性是 "动画" 的记录。如下,

    GET /books/_search{"query":{"match":{"title": "童话"}}}

查询结果如下,

    {"took": 0,"timed_out": false,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0},"hits": {"total": {"value": 2,"relation": "eq"},"max_score": 0.11190013,"hits": [{"_index": "books","_type": "_doc","_id": "1","_score": 0.11190013,"_source": {"title": "格林童话","content": "这本书介绍了很多童话故事,有白雪公主、狮子王、美人鱼等。"}},{"_index": "books","_type": "_doc","_id": "2","_score": 0.099543065,"_source": {"title": "中国童话故事","content": "这本书介绍了很多中国童话故事。"}}]}}

可以看到,查询结果中匹配了标题包含“童话”的文档,这说明 Elasticsearch 使用了中文分词器对查询字符串和文档进行了分词,并根据相关性得分返回了结果。

全文搜索以及筛选排序

在项目中,商城首页顶部提供了商品搜索栏,用户可以输入商品名称搜索自己想要的商品,搜索结果展示后,还可以进行热门、新品过滤以及价格、销量等进行排序。

可以看到搜索功能还是比较复杂的,在项目中,这些逻辑全部在 Elasticsearch 内部进行处理,代码如下,

    @RestController@AllArgsConstructor@RequestMapping("search")public class SearchController extends BaseController {private IGoodsService iGoodsService;private ElasticDocument elasticDocument;@GetMapping("result")public R result(SearchVO searchVO) throws IOException {// 获取筛选、排序条件Long memberId = MobileSecurityUtils.getUserId();String keyword = searchVO.getKeyword();Boolean filterNew = searchVO.getFilterNew();Boolean filterHot = searchVO.getFilterHot();Boolean isNew = searchVO.getIsNew();Boolean isHot = searchVO.getIsHot();Boolean isPrice = searchVO.getIsPrice();Boolean isSales = searchVO.getIsSales();String orderBy = searchVO.getOrderBy();SearchHistory searchHistory = new SearchHistory();if (memberId != null && StringUtils.isNotEmpty(keyword)) {searchHistory.setCreateTime(LocalDateTime.now());searchHistory.setUserId(memberId);searchHistory.setKeyword(keyword);}Page<SearchVO> page = getPage();// 查询包含关键字、已上架商品SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();MatchQueryBuilder matchFiler = QueryBuilders.matchQuery("isOnSale", true);MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("name", keyword);MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery("keyword", keyword);boolQueryBuilder.filter(matchFiler).should(matchQuery).should(matchPhraseQueryBuilder).minimumShouldMatch(1);searchSourceBuilder.timeout(new TimeValue(10, TimeUnit.SECONDS));// 按是否新品排序if (isNew) {searchSourceBuilder.sort(new FieldSortBuilder("isNew").order(SortOrder.DESC));}// 按是否热品排序if (isHot) {searchSourceBuilder.sort(new FieldSortBuilder("isHot").order(SortOrder.DESC));}// 按价格高低排序if (isPrice) {searchSourceBuilder.sort(new FieldSortBuilder("retailPrice").order("asc".equals(orderBy) ? SortOrder.ASC : SortOrder.DESC));}// 按销量排序if (isSales) {searchSourceBuilder.sort(new FieldSortBuilder("sales").order(SortOrder.DESC));}// 筛选新品if (filterNew) {MatchQueryBuilder filterQuery = QueryBuilders.matchQuery("isNew", true);boolQueryBuilder.filter(filterQuery);}// 筛选热品if (filterHot) {MatchQueryBuilder filterQuery = QueryBuilders.matchQuery("isHot", true);boolQueryBuilder.filter(filterQuery);}// 组装Elasticsearch查询条件searchSourceBuilder.query(boolQueryBuilder);// Elasticsearch分页相关searchSourceBuilder.from((int) (page.getCurrent() - 1) * (int) page.getSize());searchSourceBuilder.size((int) page.getSize());// 执行Elasticsearch查询List<JSONObject> list = elasticDocument.search("goods", searchSourceBuilder, JSONObject.class);List<Integer> goodsIdList = list.stream().map(jsonObject -> (Integer) jsonObject.get("id")).collect(Collectors.toList());if (goodsIdList.isEmpty()) {return R.success().add("goods", Collections.emptyList());}// 根据Elasticsearch中返回商品ID查询商品详情并保持es中的排序List<Goods> goodsList = iGoodsService.searchResult(goodsIdList);Map<Integer, Goods> goodsMap = goodsList.stream().collect(Collectors.toMap(goods -> Math.toIntExact(goods.getId()), o -> o));List<Goods> returnGoodsList = new ArrayList<>(goodsList.size());for (Integer goodsId : goodsIdList) {returnGoodsList.add(goodsMap.get(goodsId));}if (CollectionUtils.isNotEmpty(goodsList)) {AsyncManager.me().execute(new TimerTask() {@Overridepublic void run() {searchHistory.setHasGoods(true);iSearchHistoryService.save(searchHistory);}});}return R.success().add("goods", returnGoodsList);}}

这里对上面商城的搜索代码给大家做一个讲解:

  • 第一步:获取筛选、排序条件
  • 第二步:获取查询条件-用户搜索关键字、商品已上架
  • 第三步:获取排序条件-按是否新品排序、按是否热品排序、按价格高低排序、按销量排序
  • 第四步:获取过滤条件-筛选新品、筛选热品
  • 第五步:组装 Elasticsearch 查询条件以及分页条件
  • 第六步:执行 Elasticsearch 查询操作
  • 第七步:获取 Elasticsearch 中返回的商品 ID ,并根据商品 id 查询商品详情,最后商品保持 es 中的排序

总结一下

本文给大家讲解了项目中对于 elasticsearch 的使用以及代码实战讲解。希望能帮助大家更好理解 elasticsearch,大家在自己的项目中如果要引入 elasticsearch,可以直接参照本文的示例代码即可使用。

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

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

相关文章

【论文学习与撰写】,论文word文档中出现乱码的情况,文档中显示的乱码,都是英文字母之类的,但打印预览是正常的

目录 1、问题 2、解决方法 1、问题 写论文的时候&#xff0c;有时会出现乱码的情况&#xff0c; 如下图&#xff0c;这种情况&#xff0c; 可是 在打印预览的时候&#xff0c;就显示的正常 如下图&#xff0c; 2、解决方法 既然是文档正文显示错误&#xff0c;显示乱码&…

【HarmonyOS NEXT】服务端向终端推送消息——获取Push Token

【需求】 获取Push Token 【文档】 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/push-get-token-V5 【代码】 // EntryAbility.ets 文件 import { pushService } from kit.PushKit; export default class EntryAbility extends UIAbility {onCreat…

【详解】下载MySql安装教程(帮助数据库下载)

此版本是我下载的版本&#xff0c;其他版本均可以。 1.官网下载相应的版本&#xff1a;MYSQL&#xff1a;8.0.33 https://www.mysql.com/ 2.点击DOWNLOADS进入 3.在上述界面当中往下翻&#xff0c;找到社区版的下载界面 4.点进社区版的界面 前三个是Linux系统下的安装&a…

1.centos 镜像

centos 它有官网的下载地址&#xff1a;https://vault.centos.org/ 选择想要的版本&#xff0c;我选择 centos7.8 进入到镜像目录 isos 选择 x86_64 选择想要的版本&#xff0c;我选择 CentOS-7-x86_64-DVD-2003.iso 安装就正常安装就行。我选择虚拟机安装。这个参考&…

git的安装以及入门使用

文章目录 git的安装以及入门使用什么是git&#xff1f;git安装git官网 git初始化配置使用方式初始化配置&#xff1a; git的安装以及入门使用 什么是git&#xff1f; Git 是一个免费开源的分布式版本控制系统&#xff0c;使用特殊的仓库数据库记录文件变化。它记录每个文件的…

前端开发设计模式——状态模式

目录 一、状态模式的定义和特点 二、状态模式的结构与原理 1.结构&#xff1a; 2.原理&#xff1a; 三、状态模式的实现方式 四、状态模式的使用场景 1.按钮的不同状态&#xff1a; 2.页面加载状态&#xff1a; 3.用户登录状态&#xff1a; 五、状态模式的优点 1.提…

Matplotlib和Seaborn数据可视化

目录 Matplotlib图表绘制 准备工作 折线图line 柱状图bar 水平条形图barh 饼图pie 散点图scatter 气泡图csatter 箱线图boxplot 直方图hist 蜂巢图hexbin Seaborn图表绘制 准备数据 关系散点图scatterplot 关系散点线形图replot 分类散点图stripplot 分类小提…

Flink窗口分配器WindowAssigner

前言 Flink 数据流经过 keyBy 分组后&#xff0c;下一步就是 WindowAssigner。 WindowAssigner 定义了 stream 中的元素如何被分发到各个窗口&#xff0c;元素可以被分发到一个或多个窗口中&#xff0c;Flink 内置了常用的窗口分配器&#xff0c;包括&#xff1a;tumbling wi…

前缀和和差分算法

文章目录 一维前缀和一维前缀和概念一维前缀和数组的构建 二维前缀和二维前缀和概念二维前缀和数组的构建 一维差分一维差分概念一维差分数组的构建 二维差分二维差分概念二维差分数组的构建 一维前缀和 一维前缀和概念 一维前缀和是一种常用的数据预处理方法&#xff0c;它能…

JS事件和DOM

1. DOM 1.1 基本概念 DOM&#xff0c;全称 Document Object Model&#xff0c;即文档对象模型。它是 Web 上最常用的 API 之一&#xff0c;是加载在浏览器中的文档模型&#xff0c;可以将文档表示为节点树&#xff08;或称 DOM 树&#xff09;&#xff0c;其中每个节点代表文…

【协议】IIC总线协议学习

一、IIC基本介绍 设计I2C的初衷是减少电视机等复杂电子系统内部的布线数量&#xff0c;同时也降低制造成本。通过使用只有两根线的通信总线&#xff0c;它有效地减少了器件间连接的复杂性。 IIC总线是两线制总线&#xff0c;仅有串行数据线SDA和串行时钟线SCL进行通信。减少…

【Python实例】Python读取并绘制tif数据

【Python实例】Python读取并绘制tiff数据 Python实例-以全球不透水面积数据为例数据准备&#xff1a;全球不透水面积数据基于gdal库绘制tif图基于Rasterio库绘制tif图 参考 GeoTIff 是一个标准的.tif 文件或是一个图像文件格式&#xff0c;它包含了一些额外的空间信息&#xff…

prompt learning

prompt learning 对于CLIP&#xff08;如上图所示&#xff09;而言&#xff0c;对其prompt构造的更改就是在zero shot应用到下游任务的时候对其输入的label text进行一定的更改&#xff0c;比如将“A photo of a{obj}”改为“[V1][V2]…[Vn][Class]”这样可学习的V1-Vn的token…

业务开发常见问题-并发工具类

hello&#xff0c;大家好&#xff0c;本讲我们一起聊一下常见的几个并发工具类的使用和坑&#xff01; 在日常工作中&#xff0c;我们经常会遇到多线程并发问题&#xff0c;比如ThreadLocal、锁、ConcurrentHashMap、CopyOnWriteArrayList等。那么如何正常的使用呢&#xff1f;…

【最新通知】2024年Cisco思科认证CCNA详解

CCNA现在涵盖安全性、自动化和可编程性。该计划拥有一项涵盖IT职业基础知识的认证&#xff0c;包括一门考试和一门培训课程&#xff0c;助您做好准备。 CCNA培训课程和考试最近面向最新技术和工作岗位进行了重新调整&#xff0c;为您提供了向任何方向发展事业所需的基础。CCNA认…

blender分离含有多个动作的模型,并导出含有材质的fbx模型

问题背景 笔者是模型小白&#xff0c;需要将网络上下载的fbx模型中的动作&#xff0c;分离成单独的动作模型&#xff0c;经过3天摸爬滚打&#xff0c;先后使用了blender&#xff0c;3d max&#xff0c;unity&#xff0c;最终用blender完成&#xff0c;期间参考了众多网络上大佬…

【Ansiable】ansible的模块和主机清单

目录 一、介绍一些运维自动化工具 二、Ansible 概述/简介 三、Ansible 工作机制 3.1 内部工作机制 3.2 外部工作机制 四、Ansible 执行流程 五、Ansblie 安装以及日常操作模块***** 5.1 ansible 环境安装部署 5.2 ansible 命令行模块 5.2.1 command 模块 5.2.2 shel…

明源云ERP报表服务GetErpConfig.aspx接口存在敏感信息泄露

一、漏洞简介 在访问 /service/Mysoft.Report.Web.Service.Base/GetErpConfig.aspx?erpKeyerp60 路径时&#xff0c;返回了包含敏感信息的响应。这些信息包括但不限于数据库连接字符串、用户名、密码、加密密钥等。这些敏感信息的暴露可能导致以下风险&#xff1a;数据库访问…

【IPv6】IPv6 NAT66介绍

参考链接 IPv6-to-IPv6 Network Address Translation (NAT66) (ietf.org)https://datatracker.ietf.org/doc/id/draft-mrw-nat66-00.html IPv6 NAT66 NAT66&#xff0c;全称为Network Address Translation for IPv6 to IPv6&#xff0c;是一种用于IPv6网络的地址转换技术。在…

Tkinter -- python GUI学习与使用

前言 python GUI 目前pythonGUI有很多&#xff0c;哪一个最好&#xff1f; 先说说我选择的思路&#xff0c;我的目的是开发一个易用的软件&#xff0c;最重要的是稳定&#xff0c;并且碰到问题能够解决&#xff0c;因此&#xff0c;我的目标很明确&#xff0c;有比较大的用户群…