建设网站过时,临沂网,沈阳网站建设,电商网络营销♥️作者#xff1a;小宋1021 #x1f935;♂️个人主页#xff1a;小宋1021主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识#xff0c;和大家一起努力呀#xff01;#xff01;#xff01; #x1f388;#x1f388;加油#xff01; 加油#xff01…♥️作者小宋1021 ♂️个人主页小宋1021主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识和大家一起努力呀 加油 加油 加油 加油 欢迎评论 点赞 收藏 加关注 目录
初识elasticsearch
认识和安装
安装elasticsearch
安装Kibana
倒排索引
正向索引
倒排索引
正向和倒排
基础概念
文档和字段
索引和映射
mysql与elasticsearch
IK分词器
安装IK分词器
使用IK分词器
拓展词典
总结 在我们的项目之中搜索肯定是访问频率最高的页面之一。目前搜索功能是基于数据库的模糊搜索来实现的存在很多问题。
首先查询效率较低。
由于数据库模糊查询不走索引在数据量较大的时候查询性能很差。表中仅仅有不到9万条数据基于数据库查询时搜索接口的表现如图 改为基于搜索引擎后查询表现如下 需要注意的是数据库模糊查询随着表数据量的增多查询性能的下降会非常明显而搜索引擎的性能则不会随着数据增多而下降太多。目前仅10万不到的数据量差距就如此明显如果数据量达到百万、千万、甚至上亿级别这个性能差距会非常夸张。
其次功能单一
数据库的模糊搜索功能单一匹配条件非常苛刻必须恰好包含用户搜索的关键字。而在搜索引擎中用户输入出现个别错字或者用拼音搜索、同义词搜索都能正确匹配到数据。
综上在面临海量数据的搜索或者有一些复杂搜索需求的时候推荐使用专门的搜索引擎来实现搜索功能。
目前全球的搜索引擎技术排名如下 排名第一的就是我们今天要学习的elasticsearch.
elasticsearch是一款非常强大的开源搜索引擎支持的功能非常多例如 通过今天的学习大家要达成下列学习目标 理解倒排索引原理 会使用IK分词器 理解索引库Mapping映射的属性含义 能创建索引库及映射 能实现文档的CRUD 初识elasticsearch
Elasticsearch的官方网站如下 Elasticsearch官方分布式搜索和分析引擎 | Elastic 本章我们一起来初步了解一下Elasticsearch的基本原理和一些基础概念。 认识和安装
Elasticsearch是由elastic公司开发的一套搜索引擎技术它是elastic技术栈中的一部分。完整的技术栈包括 Elasticsearch用于数据存储、计算和搜索 Logstash/Beats用于数据收集 Kibana用于数据可视化
整套技术栈被称为ELK经常用来做日志收集、系统监控和状态分析等等 整套技术栈的核心就是用来存储、搜索、计算的Elasticsearch因此我们接下来学习的核心也是Elasticsearch。
我们要安装的内容包含2部分 elasticsearch存储、搜索和运算 kibana图形化展示
首先Elasticsearch不用多说是提供核心的数据存储、搜索、分析功能的。
然后是KibanaElasticsearch对外提供的是Restful风格的API任何操作都可以通过发送http请求来完成。不过http请求的方式、路径、还有请求参数的格式都有严格的规范。这些规范我们肯定记不住因此我们要借助于Kibana这个服务。
Kibana是elastic公司提供的用于操作Elasticsearch的可视化控制台。它的功能非常强大包括 对Elasticsearch数据的搜索、展示 对Elasticsearch数据的统计、聚合并形成图形化报表、图形 对Elasticsearch的集群状态监控 它还提供了一个开发控制台DevTools在其中对Elasticsearch的Restful的API接口提供了语法提示 安装elasticsearch
通过下面的Docker命令即可安装单机版本的elasticsearch docker run -d \ --name es \ -e ES_JAVA_OPTS-Xms512m -Xmx512m \ -e discovery.typesingle-node \ -v es-data:/usr/share/elasticsearch/data \ -v es-plugins:/usr/share/elasticsearch/plugins \ --privileged \ --network hm-net \ -p 9200:9200 \ -p 9300:9300 \ elasticsearch:7.12.1 注意这里我们采用的是elasticsearch的7.12.1版本由于8以上版本的JavaAPI变化很大在企业中应用并不广泛企业中应用较多的还是8以下的版本。
如果拉取镜像困难可以直接导入提供的镜像tar包 安装完成后访问9200端口即可看到响应的Elasticsearch服务的基本信息 安装Kibana
通过下面的Docker命令即可部署Kibana docker run -d \ --name kibana \ -e ELASTICSEARCH_HOSTShttp://es:9200 \ --networkhm-net \ -p 5601:5601 \ kibana:7.12.1 如果拉取镜像困难可以直接导入资料提供的镜像tar包 安装完成后直接访问5601端口即可看到控制台页面 选择Explore on my own之后进入主页面 然后选中Dev tools进入开发工具页面 倒排索引
elasticsearch之所以有如此高性能的搜索表现正是得益于底层的倒排索引技术。那么什么是倒排索引呢
倒排索引的概念是基于MySQL这样的正向索引而言的。 正向索引
我们先来回顾一下正向索引。
例如有一张名为tb_goods的表 id title price 1 小米手机 3499 2 华为手机 4999 3 华为小米充电器 49 4 小米手环 49 ... ... ...
其中的id字段已经创建了索引由于索引底层采用了B树结构因此我们根据id搜索的速度会非常快。但是其他字段例如title只在叶子节点上存在。
因此要根据title搜索的时候只能遍历树中的每一个叶子节点判断title数据是否符合要求。
比如用户的SQL语句为 select * from tb_goods where title like %手机%; 那搜索的大概流程如图 说明 1检查到搜索条件为like %手机%需要找到title中包含手机的数据 2逐条遍历每行数据每个叶子节点比如第1次拿到id为1的数据 3判断数据中的title字段值是否符合条件 4如果符合则放入结果集不符合则丢弃 5回到步骤1 综上根据id精确匹配时可以走索引查询效率较高。而当搜索条件为模糊匹配时由于索引无法生效导致从索引查询退化为全表扫描效率很差。
因此正向索引适合于根据索引字段的精确搜索不适合基于部分词条的模糊匹配。
而倒排索引恰好解决的就是根据部分词条模糊匹配的问题。 倒排索引
倒排索引中有两个非常重要的概念 文档Document用来搜索的数据其中的每一条数据就是一个文档。例如一个网页、一个商品信息 词条Term对文档数据或用户搜索数据利用某种算法分词得到的具备含义的词语就是词条。例如我是中国人就可以分为我、是、中国人、中国、国人这样的几个词条 创建倒排索引是对正向索引的一种特殊处理和应用流程如下 将每一个文档的数据利用分词算法根据语义拆分得到一个个词条 创建表每行数据包括词条、词条所在文档id、位置等信息 因为词条唯一性可以给词条创建正向索引
此时形成的这张以词条为索引的表就是倒排索引表两者对比如下
正向索引 id索引 title price 1 小米手机 3499 2 华为手机 4999 3 华为小米充电器 49 4 小米手环 49 ... ... ...
倒排索引 词条索引 文档id 小米 134 手机 12 华为 23 充电器 3 手环 4 倒排索引的搜索流程如下以搜索华为手机为例如图 流程描述
1用户输入条件华为手机进行搜索。
2对用户输入条件分词得到词条华为、手机。
3拿着词条在倒排索引中查找由于词条有索引查询效率很高即可得到包含词条的文档id1、2、3。
4拿着文档id到正向索引中查找具体文档即可由于id也有索引查询效率也很高。 虽然要先查询倒排索引再查询倒排索引但是无论是词条、还是文档id都建立了索引查询速度非常快无需全表扫描。 正向和倒排 那么为什么一个叫做正向索引一个叫做倒排索引呢 正向索引是最传统的根据id索引的方式。但根据词条查询时必须先逐条获取每个文档然后判断文档中是否包含所需要的词条是根据文档找词条的过程。 而倒排索引则相反是先找到用户要搜索的词条根据词条得到保护词条的文档的id然后根据id获取文档。是根据词条找文档的过程。
是不是恰好反过来了
那么两者方式的优缺点是什么呢
正向索引 优点 可以给多个字段创建索引 根据索引字段搜索、排序速度非常快 缺点 根据非索引字段或者索引字段中的部分词条查找时只能全表扫描。
倒排索引 优点 根据词条搜索、模糊搜索时速度非常快 缺点 只能给词条创建索引而不是字段 无法根据字段做排序 基础概念
elasticsearch中有很多独有的概念与mysql中略有差别但也有相似之处。 文档和字段
elasticsearch是面向文档Document存储的可以是数据库中的一条商品数据一个订单信息。文档数据会被序列化为json格式后存储在elasticsearch中 { id: 1, title: 小米手机, price: 3499 } { id: 2, title: 华为手机, price: 4999 } { id: 3, title: 华为小米充电器, price: 49 } { id: 4, title: 小米手环, price: 299 } 因此原本数据库中的一行数据就是ES中的一个JSON文档而数据库中每行数据都包含很多列这些列就转换为JSON文档中的字段Field。 索引和映射
随着业务发展需要在es中存储的文档也会越来越多比如有商品的文档、用户的文档、订单文档等等 所有文档都散乱存放显然非常混乱也不方便管理。
因此我们要将类型相同的文档集中在一起管理称为索引Index。例如
商品索引 { id: 1, title: 小米手机, price: 3499 } { id: 2, title: 华为手机, price: 4999 } { id: 3, title: 三星手机, price: 3999 } 用户索引 { id: 101, name: 张三, age: 21 } { id: 102, name: 李四, age: 24 } { id: 103, name: 麻子, age: 18 } 订单索引 { id: 10, userId: 101, goodsId: 1, totalFee: 294 } { id: 11, userId: 102, goodsId: 2, totalFee: 328 } 所有用户文档就可以组织在一起称为用户的索引 所有商品的文档可以组织在一起称为商品的索引 所有订单的文档可以组织在一起称为订单的索引
因此我们可以把索引当做是数据库中的表。
数据库的表会有约束信息用来定义表的结构、字段的名称、类型等信息。因此索引库中就有映射mapping是索引中文档的字段约束信息类似表的结构约束。 mysql与elasticsearch
我们统一的把mysql与elasticsearch的概念做一下对比 MySQL Elasticsearch 说明 Table Index 索引(index)就是文档的集合类似数据库的表(table) Row Document 文档Document就是一条条的数据类似数据库中的行Row文档都是JSON格式 Column Field 字段Field就是JSON文档中的字段类似数据库中的列Column Schema Mapping Mapping映射是索引中文档的约束例如字段类型约束。类似数据库的表结构Schema SQL DSL DSL是elasticsearch提供的JSON风格的请求语句用来操作elasticsearch实现CRUD
如图 那是不是说我们学习了elasticsearch就不再需要mysql了呢
并不是如此两者各自有自己的擅长之处 Mysql擅长事务类型操作可以确保数据的安全和一致性 Elasticsearch擅长海量数据的搜索、分析、计算 因此在企业中往往是两者结合使用 对安全性要求较高的写操作使用mysql实现 对查询性能要求较高的搜索需求使用elasticsearch实现 两者再基于某种方式实现数据的同步保证一致性 IK分词器
Elasticsearch的关键就是倒排索引而倒排索引依赖于对文档内容的分词而分词则需要高效、精准的分词算法IK分词器就是这样一个中文分词算法。 安装IK分词器
方案一在线安装
运行一个命令即可 docker exec -it es ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip 然后重启es容器 docker restart es 方案二离线安装
如果网速较差也可以选择离线安装。
首先查看之前安装的Elasticsearch容器的plugins数据卷目录 docker volume inspect es-plugins 结果如下 [ { CreatedAt: 2024-11-06T10:06:3408:00, Driver: local, Labels: null, Mountpoint: /var/lib/docker/volumes/es-plugins/_data, Name: es-plugins, Options: null, Scope: local } ] 可以看到elasticsearch的插件挂载到了/var/lib/docker/volumes/es-plugins/_data这个目录。我们需要把IK分词器上传至这个目录。 找到课前资料提供的ik分词器插件课前资料提供了7.12.1版本的ik分词器压缩文件你需要对其解压 然后上传至虚拟机的/var/lib/docker/volumes/es-plugins/_data这个目录 最后重启es容器 docker restart es 使用IK分词器
IK分词器包含两种模式 ik_smart智能语义切分 ik_max_word最细粒度切分 我们在Kibana的DevTools上来测试分词器首先测试Elasticsearch官方提供的标准分词器 POST /_analyze { analyzer: standard, text: 程序员学习java太棒了 } 结果如下 { tokens : [ { token : 程, start_offset : 2, end_offset : 3, type : IDEOGRAPHIC, position : 2 }, { token : 序, start_offset : 3, end_offset : 4, type : IDEOGRAPHIC, position : 3 }, { token : 员, start_offset : 4, end_offset : 5, type : IDEOGRAPHIC, position : 4 }, { token : 学, start_offset : 5, end_offset : 6, type : IDEOGRAPHIC, position : 5 }, { token : 习, start_offset : 6, end_offset : 7, type : IDEOGRAPHIC, position : 6 }, { token : java, start_offset : 7, end_offset : 11, type : ALPHANUM, position : 7 }, { token : 太, start_offset : 11, end_offset : 12, type : IDEOGRAPHIC, position : 8 }, { token : 棒, start_offset : 12, end_offset : 13, type : IDEOGRAPHIC, position : 9 }, { token : 了, start_offset : 13, end_offset : 14, type : IDEOGRAPHIC, position : 10 } ] } 可以看到标准分词器智能1字1词条无法正确对中文做分词。
我们再测试IK分词器 POST /_analyze { analyzer: ik_smart, text: 程序员学习java太棒了 } 执行结果如下 { tokens : [ { token : 程序员, start_offset : 2, end_offset : 5, type : CN_WORD, position : 1 }, { token : 学习, start_offset : 5, end_offset : 7, type : CN_WORD, position : 2 }, { token : java, start_offset : 7, end_offset : 11, type : ENGLISH, position : 3 }, { token : 太棒了, start_offset : 11, end_offset : 14, type : CN_WORD, position : 4 } ] } 拓展词典
随着互联网的发展“造词运动”也越发的频繁。出现了很多新的词语在原有的词汇列表中并不存在。比如“泰裤辣”“传智播客” 等。
IK分词器无法对这些词汇分词测试一下 POST /_analyze { analyzer: ik_max_word, text: 传智播客开设大学,真的泰裤辣 } 结果 { tokens : [ { token : 传, start_offset : 0, end_offset : 1, type : CN_CHAR, position : 0 }, { token : 智, start_offset : 1, end_offset : 2, type : CN_CHAR, position : 1 }, { token : 播, start_offset : 2, end_offset : 3, type : CN_CHAR, position : 2 }, { token : 客, start_offset : 3, end_offset : 4, type : CN_CHAR, position : 3 }, { token : 开设, start_offset : 4, end_offset : 6, type : CN_WORD, position : 4 }, { token : 大学, start_offset : 6, end_offset : 8, type : CN_WORD, position : 5 }, { token : 真的, start_offset : 9, end_offset : 11, type : CN_WORD, position : 6 }, { token : 泰, start_offset : 11, end_offset : 12, type : CN_CHAR, position : 7 }, { token : 裤, start_offset : 12, end_offset : 13, type : CN_CHAR, position : 8 }, { token : 辣, start_offset : 13, end_offset : 14, type : CN_CHAR, position : 9 } ] } 可以看到传智播客和泰裤辣都无法正确分词。
所以要想正确分词IK分词器的词库也需要不断的更新IK分词器提供了扩展词汇的功能。
1打开IK分词器config目录 注意如果采用在线安装的通过默认是没有config目录的需要把课前资料提供的ik下的config上传至对应目录。 2在IKAnalyzer.cfg.xml配置文件内容添加 ?xml version1.0 encodingUTF-8? !DOCTYPE properties SYSTEM http://java.sun.com/dtd/properties.dtd properties commentIK Analyzer 扩展配置/comment !--用户可以在这里配置自己的扩展字典 *** 添加扩展词典-- entry keyext_dictext.dic/entry /properties 3在IK分词器的config目录新建一个 ext.dic可以参考config目录下复制一个配置文件进行修改 传智播客 泰裤辣 4重启elasticsearch docker restart es # 查看 日志 docker logs -f elasticsearch 再次测试可以发现传智播客和泰裤辣都正确分词了 { tokens : [ { token : 传智播客, start_offset : 0, end_offset : 4, type : CN_WORD, position : 0 }, { token : 开设, start_offset : 4, end_offset : 6, type : CN_WORD, position : 1 }, { token : 大学, start_offset : 6, end_offset : 8, type : CN_WORD, position : 2 }, { token : 真的, start_offset : 9, end_offset : 11, type : CN_WORD, position : 3 }, { token : 泰裤辣, start_offset : 11, end_offset : 14, type : CN_WORD, position : 4 } ] } 总结
分词器的作用是什么 创建倒排索引时对文档分词 用户搜索时对输入的内容分词
IK分词器有几种模式 ik_smart智能切分粗粒度 ik_max_word最细切分细粒度
IK分词器如何拓展词条如何停用词条 利用config目录的IkAnalyzer.cfg.xml文件添加拓展词典和停用词典 在词典中添加拓展词条或者停用词条