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 更新文档

  • 用法
  1. 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,进行对比更新。

  1. 更新时增加属性

请求体中增加 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 包含 millland

或者 address 包含 millland 的记录。

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 学习(一).基础原理相关推荐

  1. ElasticSearch搜索底层基础原理总结

    目录: 1._search结果分析 2.multi-index和multi-type 3.分页查询与deep paging 4.query DSL和query string 5.mapping 6.倒 ...

  2. Elasticsearch学习(3) 深入原理

    目录 1.集群定义 2.节点类型 2.1 候选主节点 & 主节点 2.2 数据节点 & 协调节点 3.索引原理 3.1 写入数据流程/存储 4.Doc Values和倒排索引 4.1 ...

  3. 基于设计原理与理念和实践的ElasticSearch学习、ELK日志收集、网盘搜索引擎

    目录 基于设计原理与理念和实践的ElasticSearch学习 一.ES基础入门 ElasticSearch是什么? ES优点: ES缺点: ElasticSearch应用场景 ElasticSear ...

  4. 0基础怎样理解深度学习的工作原理?做个票价预测工具就懂了

    原作:Radu Raice 安妮 编译自 Medium 量子位 出品 | 公众号 QbitAI 这篇文章颇!具!人!气! 软件工程专业的学生Radu Raice近日发表了文章<Want to k ...

  5. Elasticsearch学习-Doc与Segment原理

    Elasticsearch学习-Doc与Segment原理 0x00 系列文章目录 Elasticsearch学习-关于倒排索引.DocValues.FieldData和全局序号 Elasticsea ...

  6. Spring Boot学习笔记-基础(2)

    Spring Boot学习笔记-基础(2) Spring Boot 优点: – 快速创建独立运行的Spring项目以及与主流框架集成 – 使用嵌入式的Servlet容器,应用无需打成WAR包 – st ...

  7. elasticsearch的分布式架构原理

    对于全文检索,lucene是目前最流行的搜索库.以前我们都需要学习使用lucene,基于lucene做相关的开发,学习倒排索引的原理,而现在,我们可以直接使用现成的搜索框架了,因为现在很多这种搜索框架 ...

  8. MySQL学习笔记-基础篇1

    MySQL 学习笔记–基础篇1 目录 MySQL 学习笔记--基础篇1 1. 数据库概述与MySQL安装 1.1 数据库概述 1.1.1 为什么要使用数据库 1.2 数据库与数据库管理系统 1.2.1 ...

  9. ElasticSearch学习之Kibana(一)

    文章目录 前言 安装elasticsearch elasticsearch基础 定义 基础 安装Kibana 安装 查看服务状态 Kibana索引管理 增加索引(数据库) 获取索引(数据库) 删除索引 ...

最新文章

  1. Spring Job?Quartz?XXL-Job?年轻人才做选择,艿艿全莽~
  2. Flutter 调用地图软件(高德、百度、腾讯、苹果)同时实现另类国际化
  3. 复合类型_没有学不会的python--复合类型(1)--概念和元组
  4. python多核多线程编程_python是否支持多处理器/多核编程?
  5. Oracle的闪回特性之恢复truncate删除表的数据
  6. html中给div设置的属性怎么样才能拿得到_HTML与CSS结合的三种方式:优先级比较...
  7. 如何查看python的版本号
  8. 【广告技术】用张量分解预测广告库存,广告投放更可靠!
  9. easyui table 如何只展示一条_如何使用MySQL,这些操作你得明白!
  10. 摘来的去视频网站的广告方法
  11. python精彩编程200例百度_完整word版,python经典例题100道
  12. sqlserver2005查询表字典
  13. mac google浏览器axure插件
  14. Openstack1 云计算与虚拟化概念
  15. 2016年个人总结报告PPT(刘欣)
  16. 北美中小学生实用学习网站推荐
  17. BZOJ 1216 优先队列
  18. 9个酒瓶子砸向Google:google不做坏事么?
  19. java 给word加水印,Java 实现在线给word 文档添加水印
  20. 宿主机与开发板网络共享

热门文章

  1. Good Videos
  2. 关于在wrod里如何重新排版网页复制内容
  3. raise JSONDecodeError(“Extra data“, s, end) json.decoder.JSONDecodeError: Extra data: line 1 column
  4. 【硬件工程师】JTAG接口电路上下拉 应用
  5. 试题 基础练习 十进制转十六进制
  6. 计算机关机速度,关机速度慢
  7. 2023年全国最新高校辅导员精选真题及答案28
  8. directmedia/ directrtpsetup
  9. android 离线帮助文档
  10. win7用计算机名共享打印机,win7局域网打印机共享设置(win10共享打印机设置方法)...