Elasticsearch 学习(一).基础原理
Elasticsearch
参考: 14.Elasticsearch上篇(原理) (passjava.cn)
文章目录
- Elasticsearch
- 一、Elasticsearch简介
- 1.1 什么是Elasticsearch?
- 1.2 Elasticsearch 的用途?
- 1.3 Elasticsearch 的工作原理?
- 1.4 Elasticsearch 索引是什么?
- 1.5 Logstash 的用途是什么?
- 1.6 Kibana 的用途是什么?
- 1.7 为什么使用 Elasticsearch
- 二、ES 基本概念
- 2.1 Index ( 索引 )
- 2.2 倒排索引
- 三、Docker 搭建环境
- 3.1. 搭建 Elasticsearch 环境
- 1 ) 下载镜像文件
- 2 ) 创建实例
- 3.2. 搭建 Kibana 环境
- 四、初阶检索玩法
- 4.1._cat 用法
- 4.2. 索引一个文档 ( 保存 )
- 4.3 查询文档
- 4.4 更新文档
- 4.5 删除文档和索引
- 4.6 批量导入数据
- 五、高阶检索玩法
- 5.1 两种查询方式
- 5.1.1 URL 后接参数
- 5.1.2 URL 加请求体进行检索 ( QueryDSL )
- 5.2 详解 QueryDSL 查询
- 5.2.1 全部匹配 match_all
- 5.2.2 匹配查询 match
- 5.2.3 短语匹配 match_phase
- 5.2.4 多字段匹配 multi_match
- 5.2.5 复合查询 bool
- 5.2.6 filter 过滤
- 5.2.7 term 查询
- 5.2.8 aggregations 聚合
- 5.2.9 Mapping 映射
- 六、中文分词
- 6.1 ES 中的分词的原理
- 6.1.1 ES 的分词器概念
- 6.1.2 标准分词器原理
- 6.1.3 英文和标点符号分词示例
- 6.1.4 中文分词示例
- 6.2 安装 ik 分词器
- 6.2.1 ik 分词器地址
- 6.2.2 安装 ik 分词器的方式
- 6.2.2.1 方式一:容器内安装 ik 分词器
- 6.2.2.2 方式二:映射文件安装 ik 分词器
- 6.2.2.3 方式三:Xftp 上传压缩包到映射目录
- 6.3 解压 ik 分词器到容器中
- 6.4 检查 ik 分词器安装
- 6.5 使用 ik 中文分词器
- 6.6 自定义分词词库
- 6.6.1 自定义词库的方案
- 6.6.2 搭建 nginx 环境
一、Elasticsearch简介
官方文档:https://www.elastic.co/cn/what-is/elasticsearch
1.1 什么是Elasticsearch?
Elasticsearch 是一个分布式的开源搜索和分析引擎,适用于所有类型的数据,包括文本、数字、地理空间、结构化和非结构化数据。
简单来说只要涉及搜索和分析相关的, ES 都可以做。
1.2 Elasticsearch 的用途?
Elasticsearch 在速度和可扩展性方面都表现出色,而且还能够索引多种类型的内容,这意味着其可用于多种用例:
- 应用程序搜索
- 网站搜索
- 企业搜索
- 日志处理和分析
- 基础设施指标和容器监测
- 应用程序性能监测
- 地理空间数据分析和可视化
- 安全分析
- 业务分析
1.3 Elasticsearch 的工作原理?
Elasticsearch 是在 Lucene 基础上构建而成的。ES 在 Lucence 上做了很多增强。
Lucene 是apache软件基金会 4 的 jakarta 项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。(来自百度百科)
Elasticsearch 的原始数据从哪里来?
原始数据从多个来源 ( 包括日志、系统指标和网络应用程序 ) 输入到 Elasticsearch 中。
Elasticsearch 的数据是怎么采集的?
数据采集指在 Elasticsearch 中进行索引之前解析、标准化并充实这些原始数据的过程。这些数据在 Elasticsearch 中索引完成之后,用户便可针对他们的数据运行复杂的查询,并使用聚合来检索自身数据的复杂汇总。这里用到了 Logstash,后面会介绍。
怎么可视化查看想要检索的数据?
这里就要用到 Kibana 了,用户可以基于自己的数据进行搜索、查看数据视图等。
1.4 Elasticsearch 索引是什么?
Elasticsearch 索引指相互关联的文档集合。Elasticsearch 会以 JSON 文档的形式存储数据。
每个文档都会在一组键 ( 字段或属性的名称 ) 和它们对应的值 ( 字符串、数字、布尔值、日期、数值组、地理位置或其他类型的数据 ) 之间建立联系。
Elasticsearch 使用的是一种名为倒排索引的数据结构,这一结构的设计可以允许十分快速地进行全文本搜索。倒排索引会列出在所有文档中出现的每个特有词汇,并且可以找到包含每个词汇的全部文档。
在索引过程中,Elasticsearch 会存储文档并构建倒排索引,这样用户便可以近实时地对文档数据进行搜索。索引过程是在索引 API 中启动的,通过此 API 您既可向特定索引中添加 JSON 文档,也可更改特定索引中的 JSON 文档。
1.5 Logstash 的用途是什么?
Logstash 就是 ELK
中的 L
。
Logstash 是 Elastic Stack 的核心产品之一,可用来对数据进行聚合和处理,并将数据发送到 Elasticsearch。Logstash 是一个开源的服务器端数据处理管道,允许您在将数据索引到 Elasticsearch 之前同时从多个来源采集数据,并对数据进行充实和转换。
1.6 Kibana 的用途是什么?
Kibana 是一款适用于 Elasticsearch 的数据可视化和管理工具,可以提供实时的直方图、线性图等。
项目中我们总是用 Kibana
界面来搜索测试或生产环境下的日志,来看下有没有异常信息。Kibana
就是 我们常说的 ELK
中的 K
。
1.7 为什么使用 Elasticsearch
- ES 很快,近实时的搜索平台。
- ES 具有分布式的本质特质。
- ES 包含一系列广泛的功能,比如数据汇总和索引生命周期管理。
二、ES 基本概念
2.1 Index ( 索引 )
动词:相当于 Mysql 中的 insert
名词:相当于 Mysql 中的 database
与 mysql 的对比
序号 | Mysql | Elasticsearch |
---|---|---|
1 | Mysql 服务 | ES 集群服务 |
2 | 数据库 Database | 索引 Index |
3 | 表 Table | 类型 Type |
4 | 记录 Records ( 一行行记录 ) | 文档 Document ( JSON 格式 ) |
2.2 倒排索引
假如数据库有如下电影记录:
1-大话西游
2-大话西游外传
3-解析大话西游
4-西游降魔外传
5-梦幻西游独家解析
分词:将整句分拆为单词
序号 | 保存到 ES 的词 | 对应的电影记录序号 |
---|---|---|
A | 西游 | 1,2, 3,4, 5 |
B | 大话 | 1,2, 3 |
C | 外传 | 2,4, 5 |
D | 解析 | 3,5 |
E | 降魔 | 4 |
F | 梦幻 | 5 |
G | 独家 | 5 |
检索:独家大话西游
将 独家大话西游
解析拆分成 独家
、大话
、西游
ES 中 A、B、G 记录 都有这三个词的其中一种, 所以 1,2, 3,4, 5 号记录都有相关的词被命中。
1 号记录命中 2 次, A、B 中都有 ( 命中 2
次 ) ,而且 1 号记录有 2
个词,相关性得分:2
次/2
个词=1
2 号记录命中 2 个词 A、B 中的都有 ( 命中 2
次 ) ,而且 2 号记录有 3
个词,相关性得分:2
次/3
个词= 0.67
3 号记录命中 2 个词 A、B 中的都有 ( 命中 2
次 ) ,而且 3 号记录有 3
个词,相关性得分:2
次/3
个词= 0.67
4 号记录命中 2 个词 A 中有 ( 命中 1
次 ) ,而且 4 号记录有 3
个词,相关性得分:1
次/3
个词= 0.33
5 号记录命中 2 个词 A 中有 ( 命中 2
次 ) ,而且 4 号记录有 4
个词,相关性得分:2
次/4
个词= 0.5
所以检索出来的记录顺序如下:
1-大话西游 ( 想关性得分:1 )
2-大话西游外传 ( 想关性得分:0.67 )
3-解析大话西游 ( 想关性得分:0.67 )
5-梦幻西游独家解析 ( 想关性得分:0.5 )
4-西游降魔 ( 想关性得分:0.33 )
三、Docker 搭建环境
3.1. 搭建 Elasticsearch 环境
1 ) 下载镜像文件
docker pull elasticsearch:7.4.2
2 ) 创建实例
1.映射配置文件
配置映射文件夹
mkdir -p /mydata/elasticsearch/config配置映射文件夹
mkdir -p /mydata/elasticsearch/data设置文件夹权限任何用户可读可写
chmod 777 /mydata/elasticsearch -R配置 http.host
echo "http.host: 0.0.0.0" >> /mydata/elasticsearch/config/elasticsearch.yml
2.启动 elasticsearch 容器
docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type"="single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx128m" \
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2
3.访问 elasticsearch 服务
访问:http://192.168.2.135:9200
返回的 reponse
{"name": "b141a045db17","cluster_name": "elasticsearch","cluster_uuid": "Y92qKfDCRm2AJClP7IWSrA","version": {"number": "7.4.2","build_flavor": "default","build_type": "docker","build_hash": "2f90bbf7b93631e52bafb59b3b049cb44ec25e96","build_date": "2019-10-28T20:40:44.881551Z","build_snapshot": false,"lucene_version": "8.2.0","minimum_wire_compatibility_version": "6.8.0","minimum_index_compatibility_version": "6.0.0-beta1"},"tagline": "You Know, for Search"
}
访问: 192.168.2.135:9200/_cat/nodes 访问节点信息
127.0.0.1 55 88 7 0.62 0.32 0.17 dilm * b141a045db17
3.2. 搭建 Kibana 环境
docker pull kibana:7.4.2docker run --name kibana -e ELASTICSEARCH_HOSTS=http://192.168.2.135:9200 -p 5601:5601 -d kibana:7.4.2
访问 kibana: http://192.168.2.135:5601/
四、初阶检索玩法
4.1._cat 用法
GET /_cat/nodes: 查看所有节点
GET /_cat/health: 查看 es 健康状况
GET /_cat/master: 查看主节点
GET /_cat/indices: 查看所有索引查询汇总:
/_cat/allocation
/_cat/shards
/_cat/shards/{index}
/_cat/master
/_cat/nodes
/_cat/tasks
/_cat/indices
/_cat/indices/{index}
/_cat/segments
/_cat/segments/{index}
/_cat/count
/_cat/count/{index}
/_cat/recovery
/_cat/recovery/{index}
/_cat/health
/_cat/pending_tasks
/_cat/aliases
/_cat/aliases/{alias}
/_cat/thread_pool
/_cat/thread_pool/{thread_pools}
/_cat/plugins
/_cat/fielddata
/_cat/fielddata/{fields}
/_cat/nodeattrs
/_cat/repositories
/_cat/snapshots/{repository}
/_cat/templates
4.2. 索引一个文档 ( 保存 )
例子:在 member索引下的
external类型下保存标识为
1 的数据。
- 使用 Kibana 的 Dev Tools 来创建
PUT member/external/1
{
"name":"jay huang"
}
response
{"_index" : "member",//在哪个索引"_type" : "external",//在那个类型"_id" : "1",//记录 id"_version" : 1,//版本号"result" : "created",//操作类型"_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1
}
也可以通过 Postman 工具发送请求来创建记录。
post 请求 http://192.168.2.135:9200/aaa/bbb/1{"name":"lalala" }
注意:
PUT 和 POST 都可以创建记录。
POST:如果不指定 id,自动生成 id。如果指定 id,则修改这条记录,并新增版本号。
PUT:必须指定 id,如果没有这条记录,则新增,如果有,则更新。
4.3 查询文档
请求:http://192.168.2.135:9200/member/external/1Reposne:
{"_index": "member", //在哪个索引"_type": "external", //在那个类型"_id": "1", //记录 id"_version": 2, //版本号"_seq_no": 1, //并发控制字段,每次更新就会+1,用来做乐观锁"_primary_term": 1, //同上,主分片重新分配,如重启,就会变化"found": true,"_source": { //真正的内容"name": "jay huang"}
}
_seq_no 用作乐观锁
每次更新完数据后,_seq_no 就会+1,所以可以用作并发控制。
当更新记录时,如果_seq_no 与预设的值不一致,则表示记录已经被至少更新了一次,不允许本次更新。
4.4 更新文档
- 用法
- POST 带
_update
的更新操作, 对比更新。
如果原数据没有变化,则 repsonse 中的 result 返回 noop ( 没有任何操作 ) ,version 也不会变化。
请求体中需要用 doc
将请求数据包装起来。
POST 请求:http://192.168.2.135:9200/member/external/1/_update
{"doc": {"name": "aaa"}
}响应: updated 成功
{"_index": "member","_type": "external","_id": "1","_version": 3,"result": "updated","_shards": {"total": 1,"successful": 1,"failed": 0},"_seq_no": 2,"_primary_term": 1
}响应: noop 修改数据没有变化
{"_index": "member","_type": "external","_id": "1","_version": 3,"result": "noop","_shards": {"total": 0,"successful": 0,"failed": 0},"_seq_no": 2,"_primary_term": 1
}
使用场景:对于大并发更新,建议不带 _update
。对于大并发查询,少量更新的场景,可以带_update,进行对比更新。
- 更新时增加属性
请求体中增加 age
属性
http://192.168.2.135:9200/member/external/1/_update
request:
{"doc":{"name":"bbb","age": 18}
}response:
{"_index": "member","_type": "external","_id": "1","_version": 4,"result": "updated","_shards": {"total": 1,"successful": 1,"failed": 0},"_seq_no": 3,"_primary_term": 1
}
4.5 删除文档和索引
删除文档
DELETE 请求:http://192.168.2.135:9200/aaa/bbb/1response: {"_index": "aaa","_type": "bbb","_id": "1","_version": 2,"result": "deleted","_shards": {"total": 2,"successful": 1,"failed": 0},"_seq_no": 1,"_primary_term": 1 }
删除索引
DELETE 请求:http://192.168.2.135:9200/aaa repsonse: {"acknowledged": true }
没有删除类型的功能
4.6 批量导入数据
使用 kinaba 的 dev tools 工具,输入以下语句
POST /member/external/_bulk
{"index":{"_id":"1"}}
{"name":"Jay Huang"}
{"index":{"_id":"2"}}
{"name":"Jackson Huang"}
查看所有索引
get 请求 GET /_cat/indices: 查看所有索引
拷贝官方样本数据
https://gitee.com/runewbie/learning/raw/master/ElasticSearch/resource/accounts.json#
- 在 kibana 中执行脚本
五、高阶检索玩法
5.1 两种查询方式
5.1.1 URL 后接参数
GET bank/_search?q=*&sort=account_number: asc
属性值说明:
took – ES 执行搜索的时间 ( 毫秒 )
timed_out – ES 是否超时
_shards – 有多少个分片被搜索了,以及统计了成功/失败/跳过的搜索的分片
max_score – 最高得分
hits.total.value - 命中多少条记录
hits.sort - 结果的排序 key 键,没有则按 score 排序
hits._score - 相关性得分
参考文档:
https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started-search.html
5.1.2 URL 加请求体进行检索 ( QueryDSL )
请求体中写查询条件
GET bank/_search{"query": {"match_all": {}},"sort": [{"account_number": "asc"}]
}
查询出所有,先按照 accout_number 升序排序,再按照 balance 降序排序
5.2 详解 QueryDSL 查询
DSL: Domain Specific Language 域特定语言
5.2.1 全部匹配 match_all
示例:查询所有记录,按照 balance 降序排序,只返回第 11 条记录到第 20 条记录,只显示 balance 和 firstname 字段。
GET bank/_search
{"query": {"match_all": {}},"sort": [{"balance": {"order": "desc"}}],"from": 10,"size": 10,"_source": ["balance","firstname"]
}
5.2.2 匹配查询 match
- 基本类型 ( 非字符串 ) ,精确匹配
GET bank/_search
{"query": {"match": {"account_number": "30"}}
}
- 字符串,全文检索
GET bank/_search
{"query": {"match": {"address": "mill road"}}
}
全文检索按照评分进行排序,会对检索条件进行分词匹配。
查询 address
中包含 mill
或者 road
或者 mill road
的所有记录,并给出相关性得分。
查到了 32 条记录,最高的一条记录是 Address = “990 Mill Road”,得分:8.926605. Address=“198 Mill Lane” 评分 5.4032025,只匹配到了 Mill 单词。
5.2.3 短语匹配 match_phase
将需要匹配的值当成一个整体单词 ( 不分词 ) 进行检索
GET bank/_search
{"query": {"match_phrase": {"address": "mill road"}}
}
查出 address 中包含
mill road
的所有记录,并给出相关性得分
5.2.4 多字段匹配 multi_match
GET bank/_search
{"query": {"multi_match": {"query": "mill land","fields": ["state","address"]}}
}
multi_match 中的 query 也会进行分词。
查询
state
包含mill
或land
或者
address
包含mill
或land
的记录。
5.2.5 复合查询 bool
复合语句可以合并任何其他查询语句,包括复合语句。复合语句之间可以相互嵌套,可以表达复杂的逻辑。
搭配使用 must,must_not,should
must: 必须达到 must 指定的条件。 ( 影响相关性得分 )
must_not: 必须不满足 must_not 的条件。 ( 不影响相关性得分 )
should: 如果满足 should 条件,则可以提高得分。如果不满足,也可以查询出记录。 ( 影响相关性得分 )
示例:查询出地址包含 mill,且性别为 M,年龄不等于 28 的记录,且优先展示 firstname 包含 Winnie 的记录。
GET bank/_search
{"query": {"bool": {"must": [{"match": {"address": "mill"}},{"match": {"gender": "M"}}],"must_not": [{"match": {"age": "28"}}],"should": [{"match": {"firstname": "Winnie"}}]}}
}
5.2.6 filter 过滤
不影响相关性得分,查询出满足 filter 条件的记录。
在 bool 中使用。
GET bank/_search
{"query": {"bool": {"filter": [{"range": {"age": {"gte": 18,"lte": 40}}}]}}
}
5.2.7 term 查询
匹配某个属性的值。
全文检索字段用 match,其他非 text 字段匹配用 term
keyword:文本精确匹配 ( 全部匹配 )
match_phase:文本短语匹配
非 text 字段精确匹配
GET bank/_search
{"query": {"term": {"age": "20"}}
}
5.2.8 aggregations 聚合
聚合:从数据中分组和提取数据。类似于 SQL GROUP BY 和 SQL 聚合函数。
Elasticsearch 可以将命中结果和多个聚合结果同时返回。
聚合语法:
"aggregations" : {"<聚合名称 1>" : {"<聚合类型>" : {<聚合体内容>}[,"元数据" : { [<meta_data_body>] }]?[,"aggregations" : { [<sub_aggregation>]+ }]?}[,"聚合名称 2>" : { ... }]*
}
- 示例 1:搜索 address 中包含 big 的所有人的年龄分布 ( 前 10 条 ) 以及平均年龄,以及平均薪资
GET bank/_search
{"query": {"match": {"address": "mill"}},"aggs": {"ageAggr": {"terms": {"field": "age","size": 10}},"ageAvg": {"avg": {"field": "age"}},"balanceAvg": {"avg": {"field": "balance"}}}
}
检索结果如下所示:
hits 记录返回了,三种聚合结果也返回了,平均年龄 34 随,平均薪资 25208.0,平均年龄分布:38 岁的有 2 个,28 岁的有一个,32 岁的有一个
如果不想返回 hits 结果,可以在最后面设置 size:0
GET bank/_search
{"query": {"match": {"address": "mill"}},"aggs": {"ageAggr": {"terms": {"field": "age","size": 10}}},"size": 0
}
- 示例 2:按照年龄聚合,并且查询这些年龄段的平均薪资
从结果可以看到 31 岁的有 61 个,平均薪资 28312.9,其他年龄的聚合结果类似。
- 示例 3:按照年龄分组,然后将分组后的结果按照性别分组,然后查询出这些分组后的平均薪资
GET bank/_search
{"query": {"match_all": {}},"aggs": {"ageAggr": {"terms": {"field": "age","size": 10},"aggs": {"genderAggr": {"terms": {"field": "gender.keyword","size": 10},"aggs": {"balanceAvg": {"avg": {"field": "balance"}}}}}}},"size": 0
}
从结果可以看到 31 岁的有 61 个。其中性别为 M
的 35 个,平均薪资 29565.6,性别为 F
的 26 个,平均薪资 26626.6。其他年龄的聚合结果类似
5.2.9 Mapping 映射
Mapping 是用来定义一个文档 ( document ) ,以及它所包含的属性 ( field ) 是如何存储和索引的。
- 定义哪些字符串属性应该被看做全文本属性 ( full text fields )
- 定义哪些属性包含数字,日期或地理位置
- 定义文档中的所有属性是否都能被索引 ( _all 配置 )
- 日期的格式
- 自定义映射规则来执行动态添加属性
Elasticsearch7 去掉 tpye 概念:
关系型数据库中两个数据库表示是独立的,即使他们里面有相同名称的列也不影响使用,但 ES 中不是这样的。elasticsearch 是基于 Lucence 开发的搜索引擎,而 ES 中不同 type 下名称相同的 field 最终在 Lucence 中的处理方式是一样的。
为了区分不同 type 下的同一名称的字段,Lucence 需要处理冲突,导致检索效率下降
ES7.x 版本:URL 中的 type 参数为可选。
ES8.x 版本:不支持 URL 中的 type 参数
所有类型可以参考文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html
- 查询索引的映射
如查询 my-index 索引的映射
GET /my-index/_mapping
返回结果:
{"my-index": {"mappings": {"properties": {"age": {"type": "integer"},"email": {"type": "keyword"},"employee-id": {"type": "keyword","index": false},"name": {"type": "text"}}}}
}
- 创建索引并指定映射
如创建 my-index 索引,有三个字段 age,email,name,指定类型为 interge, keyword, text
PUT /my-index
{"mappings": {"properties": {"age": {"type": "integer"},"email": {"type": "keyword"},"name": {"type": "text"}}}
}
返回结果:
{"acknowledged": true,"shards_acknowledged": true,"index": "my-index"
}
- 添加新的字段映射
如在 my-index 索引里面添加 employ-id 字段,指定类型为 keyword
PUT /my-index/_mapping
{"properties": {"employee-id": {"type": "keyword","index": false}}
}
- 更新映射
我们不能更新已经存在的映射字段,必须创建新的索引进行数据迁移。
- 数据迁移
POST _reindex
{"source": {"index": "twitter"},"dest": {"index": "new_twitter"}
}
六、中文分词
ES 内置了很多种分词器,但是对中文分词不友好,所以我们需要借助第三方中文分词工具包。
6.1 ES 中的分词的原理
6.1.1 ES 的分词器概念
ES 的一个分词器 ( tokenizer ) 接收一个字符流,将其分割为独立的词元 ( tokens ) ,然后输出词元流。
ES 提供了很多内置的分词器,可以用来构建自定义分词器 ( custom ananlyzers )
6.1.2 标准分词器原理
比如 stadard tokenizer 标准分词器,遇到空格进行分词。该分词器还负责记录各个词条 ( term ) 的顺序或 position 位置 ( 用于 phrase 短语和 word proximity 词近邻查询 ) 。每个单词的字符偏移量 ( 用于高亮显示搜索的内容 ) 。
6.1.3 英文和标点符号分词示例
查询示例如下:
POST _analyze
{"analyzer": "standard","text": "Do you know why I want to study ELK? 2 3 33..."
}
结果
do, you, know, why, i, want, to, study, elk, 2,3,33
从查询结果可以看到:
(1)标点符号没有分词。
(2)数字会进行分词。
6.1.4 中文分词示例
这种分词器对中文的分词支持不友好,会将词语分词为单独的汉字。比如下面的示例会将 今天吃饭
分词为 今,天,吃,饭,期望分词为
今天,
吃饭`。
可以安装 ik 分词器来更加友好的支持中文分词。
6.2 安装 ik 分词器
6.2.1 ik 分词器地址
ik 分词器地址:
https://github.com/medcl/elasticsearch-analysis-ik/releases
先检查 ES 版本,我安装的版本是 7.4.2
,所以我们安装 ik 分词器的版本也选择 7.4.2
http://192.168.2.35:9200/
{"name": "b141a045db17","cluster_name": "elasticsearch","cluster_uuid": "Y92qKfDCRm2AJClP7IWSrA","version": {"number": "7.4.2","build_flavor": "default","build_type": "docker","build_hash": "2f90bbf7b93631e52bafb59b3b049cb44ec25e96","build_date": "2019-10-28T20:40:44.881551Z","build_snapshot": false,"lucene_version": "8.2.0","minimum_wire_compatibility_version": "6.8.0","minimum_index_compatibility_version": "6.0.0-beta1"},"tagline": "You Know, for Search"
}
检查是否安装unzip
yum list | grep zip/unzip
如果有这个问题
就需要更换yum数据源
# 进入文件
cd /etc/yum/repos.d/
# 备份
mv CentOS-Base.repo CentOS-Base.repo.bk
# 更换新的数据源(wget不存在可参考博客:https://blog.csdn.net/qq_34497272/article/details/119418912)
wget -O /etc/yum/repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
# 清除缓存
yum clean all
yum makecache
安装zip
# 安装压缩命令zip
yum install zip
# 安装解压unzip
yum install unzip
6.2.2 安装 ik 分词器的方式
6.2.2.1 方式一:容器内安装 ik 分词器
- 进入 es 容器内部 plugins 目录
docker exec -it <容器 id> /bin/bash
- 获取 ik 分词器压缩包
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-analysis-ik-7.4.2.zip
- 解压缩 ik 压缩包
unzip 压缩包
- 删除下载的压缩包
rm -rf *.zip
6.2.2.2 方式二:映射文件安装 ik 分词器
进入到映射文件夹
cd /mydata/elasticsearch/plugins
下载安装包
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-analysis-ik-7.4.2.zip
- 解压缩 ik 压缩包
unzip 压缩包
- 删除下载的压缩包
rm -rf *.zip
6.2.2.3 方式三:Xftp 上传压缩包到映射目录
先用 XShell 工具连接虚拟机 ,然后用 Xftp 将下载好的安装包复制到虚拟机。
6.3 解压 ik 分词器到容器中
- 解压 ik 分词器到当前目录的 ik 文件夹下。
命令格式:unzip <ik 分词器压缩包>
实例:
unzip ELK-IKv7.4.2.zip -d ./ik
- 修改文件夹权限为可读可写。
chmod -R 777 ik/
- 删除 ik 分词器压缩包
rm ELK-IKv7.4.2.zip
6.4 检查 ik 分词器安装
- 进入到容器中
docker exec -it <容器 id> /bin/bash
- 查看 Elasticsearch 的插件
elasticsearch-plugin list
结果如下,说明 ik 分词器安装好了。是不是很简单。
ik
然后退出 Elasticsearch 容器,并重启 Elasticsearch 容器
exit
docker restart elasticsearch
6.5 使用 ik 中文分词器
ik 分词器有两种模式
- 智能分词模式 ( ik_smart )
- 最大组合分词模式 ( ik_max_word )
我们先看下 智能分词
模式的效果。比如对于 一颗小星星
进行中文分词,得到的两个词语:一颗
、小星星
我们在 Dev Tools Console 输入如下查询
POST _analyze
{"analyzer": "ik_smart","text": "一颗小星星"
}
再来看下 最大组合分词模式
。输入如下查询语句
POST _analyze
{"analyzer": "ik_max_word","text": "一颗小星星"
}
另外一个中文分词。比如搜索 悟空哥聊架构,期望结果:悟空哥、聊、架构三个词语。
实际结果:悟、空哥、聊、架构四个词语。ik 分词器将悟空哥分词了,认为 空哥
是一个词语。所以需要让 ik 分词器知道 悟空哥
是一个词语,不需要拆分。那怎么办做呢?
6.6 自定义分词词库
6.6.1 自定义词库的方案
方案
新建一个词库文件,然后在 ik 分词器的配置文件中指定分词词库文件的路径。可以指定本地路径,也可以指定远程服务器文件路径。这里我们使用远程服务器文件的方案,因为这种方案可以支持热更新 ( 更新服务器文件,ik 分词词库也会重新加载 ) 。
修改配置文件
ik 分词器的配置文件在容器中的路径:
/usr/share/elasticsearch/plugins/ik/config/IKAnalyzer.cfg.xml。
修改这个文件可以通过修改映射文件,文件路径:
/mydata/elasticsearch/plugins/ik/config/IKAnalyzer.cfg.xml
编辑配置文件:
vim /mydata/elasticsearch/plugins/ik/config/IKAnalyzer.cfg.xml
内容
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties><comment>IK Analyzer 扩展配置</comment><!--用户可以在这里配置自己的扩展字典 --><entry key="ext_dict">custom/mydict.dic;custom/single_word_low_freq.dic</entry><!--用户可以在这里配置自己的扩展停止词字典--><entry key="ext_stopwords">custom/ext_stopword.dic</entry><!--用户可以在这里配置远程扩展字典 --><entry key="remote_ext_dict">location</entry><!--用户可以在这里配置远程扩展停止词字典--><entry key="remote_ext_stopwords">http://xxx.com/xxx.dic</entry>
</properties>
修改配置 remote_ext_dict
的属性值,指定一个 远程网站文件的路径,比如 http://www.xxx.com/ikwords.text。
这里我们可以自己搭建一套 nginx 环境,然后把 ikwords.text 放到 nginx 根目录。
6.6.2 搭建 nginx 环境
方案:首先获取 nginx 镜像,然后启动一个 nginx 容器,然后将 nginx 的配置文件拷贝到根目录,再删除原 nginx 容器,再用映射文件夹的方式来重新启动 nginx 容器。
- 通过 docker 容器安装 nginx 环境。
docker run -p 80:80 --name nginx -d nginx:1.10
- 拷贝 nginx 容器的配置文件到 mydata 目录的 conf 文件夹
cd /mydata
docker container cp nginx:/etc/nginx ./conf
- mydata 目录 里面创建 nginx 目录
mkdir nginx
- 移动 conf 文件夹到 nginx 映射文件夹
mv conf nginx/
- 终止并删除原 nginx 容器
docker stop nginx
docker rm <容器 id>
- 启动新的容器
docker run -p 80:80 --name nginx \
-v /mydata/nginx/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx \
-v /mydata/nginx/conf:/etc/nginx \
-d nginx:1.10
- 访问 nginx 服务
192.168.2.135
报 403 Forbidden, nginx/1.10.3 则表示 nginx 服务正常启动。403 异常的原因是 nginx 服务下没有文件。
- nginx 目录新建一个 html 文件
cd /mydata/nginx/html
vim index.html
hello passjava
再次访问 nginx 服务
浏览器打印 hello passjava。说明访问 nginx 服务的页面没有问题。
创建 ik 分词词库文件
cd /mydata/nginx/html
mkdir ik
cd ik
vim ik.txt
填写 悟空哥
,并保存文件。
- 访问词库文件
http://192.168.2.135/ik/ik.txt
浏览器会输出一串乱码,可以先忽略乱码问题。说明词库文件可以访问到。
- 修改 ik 分词器配置
cd /mydata/elasticsearch/plugins/ik/config
vim IKAnalyzer.cfg.xml
- 重启 elasticsearch 容器并设置每次重启机器后都启动 elasticsearch 容器。
docker restart elasticsearch
docker update elasticsearch --restart=always
- 再次查询分词结果
可以看到 悟空哥聊架构
被拆分为 悟空哥
、聊
、架构
三个词语,说明自定义词库中的 悟空哥
有作用。
Elasticsearch 学习(一).基础原理相关推荐
- ElasticSearch搜索底层基础原理总结
目录: 1._search结果分析 2.multi-index和multi-type 3.分页查询与deep paging 4.query DSL和query string 5.mapping 6.倒 ...
- Elasticsearch学习(3) 深入原理
目录 1.集群定义 2.节点类型 2.1 候选主节点 & 主节点 2.2 数据节点 & 协调节点 3.索引原理 3.1 写入数据流程/存储 4.Doc Values和倒排索引 4.1 ...
- 基于设计原理与理念和实践的ElasticSearch学习、ELK日志收集、网盘搜索引擎
目录 基于设计原理与理念和实践的ElasticSearch学习 一.ES基础入门 ElasticSearch是什么? ES优点: ES缺点: ElasticSearch应用场景 ElasticSear ...
- 0基础怎样理解深度学习的工作原理?做个票价预测工具就懂了
原作:Radu Raice 安妮 编译自 Medium 量子位 出品 | 公众号 QbitAI 这篇文章颇!具!人!气! 软件工程专业的学生Radu Raice近日发表了文章<Want to k ...
- Elasticsearch学习-Doc与Segment原理
Elasticsearch学习-Doc与Segment原理 0x00 系列文章目录 Elasticsearch学习-关于倒排索引.DocValues.FieldData和全局序号 Elasticsea ...
- Spring Boot学习笔记-基础(2)
Spring Boot学习笔记-基础(2) Spring Boot 优点: – 快速创建独立运行的Spring项目以及与主流框架集成 – 使用嵌入式的Servlet容器,应用无需打成WAR包 – st ...
- elasticsearch的分布式架构原理
对于全文检索,lucene是目前最流行的搜索库.以前我们都需要学习使用lucene,基于lucene做相关的开发,学习倒排索引的原理,而现在,我们可以直接使用现成的搜索框架了,因为现在很多这种搜索框架 ...
- MySQL学习笔记-基础篇1
MySQL 学习笔记–基础篇1 目录 MySQL 学习笔记--基础篇1 1. 数据库概述与MySQL安装 1.1 数据库概述 1.1.1 为什么要使用数据库 1.2 数据库与数据库管理系统 1.2.1 ...
- ElasticSearch学习之Kibana(一)
文章目录 前言 安装elasticsearch elasticsearch基础 定义 基础 安装Kibana 安装 查看服务状态 Kibana索引管理 增加索引(数据库) 获取索引(数据库) 删除索引 ...
最新文章
- Spring Job?Quartz?XXL-Job?年轻人才做选择,艿艿全莽~
- Flutter 调用地图软件(高德、百度、腾讯、苹果)同时实现另类国际化
- 复合类型_没有学不会的python--复合类型(1)--概念和元组
- python多核多线程编程_python是否支持多处理器/多核编程?
- Oracle的闪回特性之恢复truncate删除表的数据
- html中给div设置的属性怎么样才能拿得到_HTML与CSS结合的三种方式:优先级比较...
- 如何查看python的版本号
- 【广告技术】用张量分解预测广告库存,广告投放更可靠!
- easyui table 如何只展示一条_如何使用MySQL,这些操作你得明白!
- 摘来的去视频网站的广告方法
- python精彩编程200例百度_完整word版,python经典例题100道
- sqlserver2005查询表字典
- mac google浏览器axure插件
- Openstack1 云计算与虚拟化概念
- 2016年个人总结报告PPT(刘欣)
- 北美中小学生实用学习网站推荐
- BZOJ 1216 优先队列
- 9个酒瓶子砸向Google:google不做坏事么?
- java 给word加水印,Java 实现在线给word 文档添加水印
- 宿主机与开发板网络共享
热门文章
- Good Videos
- 关于在wrod里如何重新排版网页复制内容
- raise JSONDecodeError(“Extra data“, s, end) json.decoder.JSONDecodeError: Extra data: line 1 column
- 【硬件工程师】JTAG接口电路上下拉 应用
- 试题 基础练习 十进制转十六进制
- 计算机关机速度,关机速度慢
- 2023年全国最新高校辅导员精选真题及答案28
- directmedia/ directrtpsetup
- android 离线帮助文档
- win7用计算机名共享打印机,win7局域网打印机共享设置(win10共享打印机设置方法)...