一、全文检索
1、什么是全文检索
全文索引是一种通过对文本内容进行全面索引和搜索的技术。它可以快速的在大量文本数据中查找包含特定关键词或短语的文档,并返回相关的搜索结果。
全文检索广泛应用于各种信息管理系统和应用中,如搜索引擎、文档管理系统、电子邮件客户端、新闻聚合网站等。它可以帮助用户快速定位所需信息,提高检索效率和准确性。
查询:有明确的搜索条件边界。比如,年龄 15~25 岁,颜色 = 红色,价格 < 3000,这里的 15、25、红色、3000 都是条件边界。即有明确的范围界定。
检索:即全文检索,无搜索条件边界,召回结果取决于相关性,其相关性计算无明确边界性条件,如同义词、谐音、别名、错别字、混淆词、网络热梗等均可成为其相关性判断依据。
2、全文检索原理
在全文检索中,首先需要对文本数据进行处理,包括分词、去除停用词等。然后,对处理后的文本数据建立索引,索引会记录每个单词在文档中的位置信息以及其他相关的元数据,如词频、权重等。这个过程通常使用倒排索引(inverted index)来实现,倒排索引将单词映射到包含该单词的文档列表中,以便快速定位相关文档。
当用户发起搜索请求时,搜索引擎会根据用户提供的关键词或短语,在建立好的索引中查找匹配的文档。搜索引擎会根据索引中的信息计算文档的相关性,并按照相关性排序返回搜索结果。用户可以通过不同的搜索策略和过滤条件来精确控制搜索结果的质量和范围。
3、什么是倒排索引
正排索引(Forward Index)和倒排索引(Inverted Index)是全文检索中常用的两种索引结构,它们在索引和搜索的过程中扮演不同的角色。
正排索引(正向索引)
正排索引是将文档按顺序排列并进行编号的索引结构。每个文档都包含了完整的文本内容,以及其他相关的属性或元数据,如标题、作者、发布日期等。在正排索引中,可以根据文档编号或其他属性快速定位和访问文档的内容。正排索引适合用于需要对文档进行整体检索和展示的场景,但对于包含大量文本内容的数据集来说,正排索引的存储和查询效率可能会受到限制。
在MySQL 中通过ID查找就是一种正排索引的应用。
倒排索引(反向索引)
倒排索引是根据单词或短语建立的索引结构。它将每个单词映射到包含该单词的文档列表中。倒排索引的建立过程是先对文档进行分词处理,然后记录每个单词在哪些文档中出现,以及出现的位置信息。通过倒排索引,可以根据关键词或短语快速找到包含这些词语的文档,并确定它们的相关性。倒排索引适用于在大规模文本数据中进行关键词搜索和相关性排序的场景,它能够快速定位文档,提高搜索效率。
我们在创建文章的时候,建立一个关键词与文章的对应关系表,就可以称之为倒排索引。如下图所示:
|------------|---------|--------|
| 关键词 | 文章ID | 是否命中索引 |
| Java | 1,2 | √ |
| 设计模式 | 1,2,3,4 | √ |
| 多线程 | 2 | |
| JavaScript | 4 | |
二、Elasticsearch简介
1、介绍
ElasticSearch(简称ES)是一个开源的分布式搜索和数据分析引擎,是用Java开发并且是当前最流行的开源的企业级搜索引擎,能够达到近实时搜索,它专门设计用于处理大规模的文本数据和实现高性能的全文检索。
以下是一些 Elasticsearch 的特点和优势:
- 分布式架构:Elasticsearch 是一个分布式系统,可以轻松地水平扩展,处理大规模的数据集和高并发的查询请求。
- 全文检索功能:Elasticsearch 提供了强大的全文检索功能,包括分词、词项查询、模糊匹配、多字段搜索等,并支持丰富的查询语法和过滤器。
- 多语言支持:Elasticsearch 支持多种语言的分词器和语言处理器,可以很好地处理不同语言的文本数据。
- 高性能:Elasticsearch 使用倒排索引和缓存等技术,具有快速的搜索速度和高效的查询性能。
- 实时性:Elasticsearch 支持实时索引和搜索,可以几乎实时地将文档添加到索引中,并立即可见。
- 易用性:Elasticsearch 提供了简单易用的 RESTful API,方便进行索引管理、查询操作和数据分析。
官方网站: Elasticsearch Platform --- Find real-time answers at scale | Elastic
下载地址: https://www.elastic.co/cn/downloads/past-releases#elasticsearch

2、应用场景
只要用到搜索的场景,ES几乎都可以是最好的选择。国内现在有大量的公司都在使用 Elasticsearch,包括携程、滴滴、今日头条、饿了么、360安全、小米、vivo等诸多知名公司。除了搜索之外,结合Kibana、Logstash、Beats,Elastic Stack还被广泛运用在大数据近实时分析领域,包括日志分析、指标监控、信息安全等多个领域。它可以帮助你探索海量结构化、非结构化数据,按需创建可视化报表,对监控数据设置报警阈值,甚至通过使用机器学习技术,自动识别异常状况。
- 搜索引擎
- 站内搜索
- 日志管理与分析
- 大数据分析
3、技术选型

三、Elasticsearch安装
安装文档:Install Elasticsearch from archive on Linux or MacOS | Elasticsearch Guide [7.17] | Elastic
1、windows安装ElasticSearch
1)下载ElasticSearch(选择版本:7.17.3)
下载地址: https://www.elastic.co/cn/downloads/past-releases#elasticsearch
windows
https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.3-windows-x86_64.zip
ElasticSearch文件目录结构
|---------|---------------------------------------------------|
| 目录 | 描述 |
| bin | 脚本文件,包括启动elasticsearch,安装插件,运行统计数据等 |
| config | 配置文件目录,如elasticsearch配置、角色配置、jvm配置等。 |
| jdk | 7.x 以后特有,自带的java环境,8.x版本自带jdk17 |
| data | 默认的数据存放目录,包含节点、分片、索引、文档的所有数据,生产环境需要修改。 |
| lib | elasticsearch依赖的Java类库 |
| logs | 默认的日志文件存储路径,生产环境需要修改。 |
| modules | 包含所有的Elasticsearch模块,如Cluster、Discovery、Indices等。 |
| plugins | 已安装插件目录 |
2)配置jdk环境
ES比较耗内存,建议虚拟机4G或以上内存,JVM1g以上的内存分配。运行Elasticsearch,需安装并配置JDK。各个版本对Java的依赖 Support Matrix | Elastic,但是整体来说7.17.x之前的都支持JDK8。
7.0开始,内置了Java环境。ES的JDK环境变量生效的优先级配置顺序ES_JAVA_HOME>JAVA_HOME>ES_HOME
- ES_JAVA_HOME:这个环境变量用于指定Elasticsearch使用的Java运行时环境的路径。在启动Elasticsearch时,它会检查ES_JAVA_HOME环境变量并使用其中的Java路径。
- ES_HOME:这个环境变量指定Elasticsearch的安装路径。它用于定位Elasticsearch的配置文件、插件和其他相关资源。设置ES_HOME环境变量可以让您在命令行中更方便地访问Elasticsearch的目录结构和文件。
可以参考es的环境文件elasticsearch-env.bat

windows下,设置ES_JAVA_HOME和ES_HOME的环境变量

3)启动ElasticSearch服务
进入bin目录,直接运行elasticsearch.bat
测试,浏览器中访问:http://localhost:9200/

2、centos7安装ElastiscSearch
1)下载ElasticSearch
# centos7
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.3-linux-x86_64.tar.gz
2)配置jdk环境
# linux 进入用户主目录,比如/home/es目录下,设置用户级别的环境变量
cd /home
mkdir es
cd es
vim .bash_profile
#设置ES_JAVA_HOME和ES_HOME的路径
export ES_JAVA_HOME=/usr/local/elasticsearch/elasticsearch-7.17.3/jdk/
export ES_HOME=/usr/local/elasticsearch/elasticsearch-7.17.3
#执行以下命令使配置生效
source .bash_profile
3)配置ElasticSearch
修改elasticsearch.yml配置
# 切换到ES_HOME的config目录下
vim elasticsearch.yml
#开启远程访问
network.host: 0.0.0.0
#单节点模式 初学者建议设置为此模式
discovery.type: single-node
ElasticSearch配置参数
参考: Important Elasticsearch configuration | Elasticsearch Guide [7.17] | Elastic
当前节点所属集群名称,多个节点如果要组成同一个集群,那么集群名称一定要配置成相同。默认值elasticsearch,生产环境建议根据ES集群的使用目的修改成合适的名字。不要在不同的环境中重用相同的集群名称,否则,节点可能会加入错误的集群。
当前节点名称,默认值当前节点部署所在机器的主机名,所以如果一台机器上要起多个ES节点的话,需要通过配置该属性明确指定不同的节点名称。
- path.data
配置数据存储目录,比如索引数据等,默认值 $ES_HOME/data,生产环境下强烈建议部署到另外的安全目录,防止ES升级导致数据被误删除。
- path.logs
配置日志存储目录,比如运行日志和集群健康信息等,默认值 $ES_HOME/logs,生产环境下强烈建议部署到另外的安全目录,防止ES升级导致数据被误删除。
- bootstrap.memory_lock
配置ES启动时是否进行内存锁定检查,默认值true。
ES对于内存的需求比较大,一般生产环境建议配置大内存,如果内存不足,容易导致内存交换到磁盘,严重影响ES的性能。所以默认启动时进行相应大小内存的锁定,如果无法锁定则会启动失败。
非生产环境可能机器内存本身就很小,能够供给ES使用的就更小,如果该参数配置为true的话很可能导致无法锁定内存以致ES无法成功启动,此时可以修改为false。
- network.host
节点对外提供服务的地址以及集群内通信的ip地址,默认值为当前节点所在机器的本机回环地址127.0.0.1 和[::1],这就导致默认情况下只能通过当前节点所在主机访问当前节点。
- http.port
配置当前ES节点对外提供服务的http端口,默认 9200
- transport.port:
节点通信端口号,默认 9300
- discovery.seed_hosts
配置参与集群节点发现过程的主机列表,说白一点就是集群中所有节点所在的主机列表,可以是具体的IP地址,也可以是可解析的域名。
- cluster.initial_master_nodes
配置ES集群初始化时参与master选举的节点名称列表,必须与node.name配置的一致。ES集群首次构建完成后,应该将集群中所有节点的配置文件中的cluster.initial_master_nodes配置项移除,重启集群或者将新节点加入某个已存在的集群时切记不要设置该配置项。
4)配置jvm参数
修改config/jvm.options配置文件,调整jvm堆内存大小
vim jvm.options
-Xms4g
-Xmx4g
配置的建议
- Xms和Xms设置成---样
- Xmx不要超过机器内存的50%
- 不要超过30GB - A Heap of Trouble: Managing Elasticsearch's Managed Heap | Elastic Blog
5)启动ElasticSearch服务
ES不允许使用root账号启动服务,如果你当前账号是root,则需要创建一个专有账户
#非root用户启动
bin/elasticsearch
# -d 后台启动
bin/elasticsearch -d
注意:es默认不能用root用户启动,生产环境建议为elasticsearch创建用户。
#为elaticsearch创建用户并赋予相应权限
adduser es
passwd es
chown -R es:es elasticsearch-7.17.3
6)启动ES服务常见错误解决方案
如果ES服务启动异常,会有提示:

1\]: max file descriptors \[4096\] for elasticsearch process is too low, increase to at least \[65536
ES因为需要大量的创建索引文件,需要大量的打开系统的文件,所以我们需要解除linux系统当中打开文件最大数目的限制,不然ES启动就会抛错
#切换到root用户
vim /etc/security/limits.conf
末尾添加如下配置:
* soft nofile 65536
* hard nofile 65536
* soft nproc 4096
* hard nproc 4096
2\]: max number of threads \[1024\] for user \[es\] is too low, increase to at least \[4096
vim /etc/security/limits.d/20-nproc.conf 改为如下配置:
vim /etc/security/limits.d/20-nproc.conf
改为如下配置:
* soft nproc 4096
3\]: max virtual memory areas vm.max_map_count \[65530\] is too low, increase to at least \[262144
最大虚拟内存太小,调大系统的虚拟内存
vim /etc/sysctl.conf
追加以下内容:
vm.max_map_count=262144
保存退出之后执行如下命令:
sysctl -p
4\]: the default discovery settings are unsuitable for production use; at least one of \[discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes\] must be configured
缺少默认配置,至少需要配置discovery.seed_hosts/discovery.seed_providers/cluster.initial_master_nodes中的一个参数.
* discovery.seed_hosts: 集群主机列表
* discovery.seed_providers: 基于配置文件配置集群主机列表
* cluster.initial_master_nodes: 启动时初始化的参与选主的node,生产环境必填
vim config/elasticsearch.yml
#添加配置
discovery.seed_hosts: ["127.0.0.1"]
cluster.initial_master_nodes: ["node-1"]
#或者指定配置单节点(集群单节点)
discovery.type: single-node
### 3、客户端Kibana安装
Kibana是一个开源分析和可视化平台,旨在与Elasticsearch协同工作。
参考文档:[Quick start \| Kibana Guide \[7.17\] \| Elastic](https://www.elastic.co/guide/en/kibana/7.17/get-started.html "Quick start | Kibana Guide [7.17] | Elastic")
#### 1)下载并解压缩Kibana
下载地址:[https://www.elastic.co/cn/downloads/past-releases#kibana](https://www.elastic.co/cn/downloads/past-releases#kibana "https://www.elastic.co/cn/downloads/past-releases#kibana")
选择版本:7.17.3

#windows
https://artifacts.elastic.co/downloads/kibana/kibana-7.17.3-windows-x86_64.zip
#linux
wget https://artifacts.elastic.co/downloads/kibana/kibana-7.17.3-linux-x86_64.tar.gz
#### 2)修改Kibana.yml
vim config/kibana.yml
server.port: 5601 #指定Kibana服务器监听的端口号
server.host: "localhost" #指定Kibana服务器绑定的主机地址
elasticsearch.hosts: ["http://localhost:9200"] #指定Kibana连接到的Elasticsearch实例的访问地址
i18n.locale: "zh-CN" #将 Kibana 的界面语言设置为简体中文
#### 3)运行Kibana
**windows**
直接执行kibana.bat
**Linux**
注意:kibana也需要非root用户启动
bin/kibana
#后台启动
nohup bin/kibana &
#查询kibana进程
netstat -tunlp | grep 5601
#### 4)访问Kibana: [http://localhost:5601/app/dev_tools#/console](http://localhost:5601/app/dev_tools#/console "http://localhost:5601/app/dev_tools#/console")

**cat API**
cat API 是 Elasticsearch 提供的一个用于查看和显示集群信息的 RESTful API。它可以用于获取关于索引、节点、分片、健康状态等各种集群相关的信息。
/_cat/allocation #查看单节点的shard分配整体情况
/_cat/shards #查看各shard的详细情况
/_cat/shards/{index} #查看指定分片的详细情况
/_cat/master #查看master节点信息
/_cat/nodes #查看所有节点信息
/_cat/indices #查看集群中所有index的详细信息
/_cat/indices/{index} #查看集群中指定index的详细信息
/_cat/segments #查看各index的segment详细信息,包括segment名, 所属shard, 内存(磁盘)占用大小, 是否刷盘
/_cat/segments/{index}#查看指定index的segment详细信息
/_cat/count #查看当前集群的doc数量
/_cat/count/{index} #查看指定索引的doc数量
/_cat/recovery #查看集群内每个shard的recovery过程.调整replica。
/_cat/recovery/{index}#查看指定索引shard的recovery过程
/_cat/health #查看集群当前状态:红、黄、绿
/_cat/pending_tasks #查看当前集群的pending task
/_cat/aliases #查看集群中所有alias信息,路由配置等
/_cat/aliases/{alias} #查看指定索引的alias信息
/_cat/thread_pool #查看集群各节点内部不同类型的threadpool的统计信息,
/_cat/plugins #查看集群各个节点上的plugin信息
/_cat/fielddata #查看当前集群各个节点的fielddata内存使用情况
/_cat/fielddata/{fields} #查看指定field的内存使用情况,里面传field属性对应的值
/_cat/nodeattrs #查看单节点的自定义属性
/_cat/repositories #输出集群中注册快照存储库
/_cat/templates #输出当前正在存在的模板信息
### 4、Elasticsearch安装分词插件
Elasticsearch提供插件机制对系统进行扩展,以安装分词插件为例:
**在线安装analysis-icu** **分词** **插件**
#查看已安装插件
bin/elasticsearch-plugin list
#安装插件
bin/elasticsearch-plugin install analysis-icu
#删除插件
bin/elasticsearch-plugin remove analysis-icu
注意:安装和删除完插件后,需要重启ES服务才能生效。
测试分词效果
# _analyzer API可以用来查看指定分词器的分词结果
POST _analyze
{
"analyzer":"icu_analyzer",
"text":"中华人民共和国"
}

**离线安装** **ik中文分词插件**
本地下载[elasticsearch-analysis-ik-7.17.3.zip](https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.17.3/elasticsearch-analysis-ik-7.17.3.zip "elasticsearch-analysis-ik-7.17.3.zip")插件,解压,然后手动上传到elasticsearch的plugins目录,然后重启ES实例就可以了。
ik中文分词插件:[https://github.com/medcl/elasticsearch-analysis-ik](https://github.com/medcl/elasticsearch-analysis-ik "https://github.com/medcl/elasticsearch-analysis-ik")
测试分词效果
#ES的默认分词设置是standard,会单字拆分
POST _analyze
{
"analyzer":"standard",
"text":"中华人民共和国"
}
#ik_smart:会做最粗粒度的拆
POST _analyze
{
"analyzer": "ik_smart",
"text": "中华人民共和国"
}
#ik_max_word:会将文本做最细粒度的拆分
POST _analyze
{
"analyzer":"ik_max_word",
"text":"中华人民共和国"
}
## 四、Elasticsearch使用
### 1、ElasticSearch核心概念
#### 1)节点:Node
一个节点就是一个Elasticsearch的实例,可以理解为一个 ES 的进程。
注意:一个节点 ≠ 一台服务器

#### 2)角色:Roles
ES的角色分类:
* 主节点(active master):一般指活跃的主节点,一个集群中只能有一个,主要作用是对集群的管理。
* 候选节点(master-eligible):当主节点发生故障时,参与选举,也就是主节点的替代节点。
* 数据节点(data node):数据节点保存包含已编入索引的文档的分片。数据节点处理数据相关操作,如 CRUD、搜索和聚合。这些操作是 I/O 密集型、内存密集型和 CPU 密集型的。监控这些资源并在它们过载时添加更多数据节点非常重要。
* 预处理节点(ingest node):预处理节点有点类似于logstash的消息管道,所以也叫ingest pipeline,常用于一些数据写入之前的预处理操作。
注意:如果 node.roles 为缺省配置,那么当前节点具备所有角色。
**3)索引:Index**
索引在 ES 中所表述的含义和 MySQL 中的索引完全不同,在 MySQL 中索引指的是加速数据查询的一种特殊的数据结构,如 normal index。
而在 ES 中,索引表述的含义等价于 MySQL 中的表(仅针对 ES 7.x 以后版本),注意这里只是类比去理解,索引并不等于表。
在 ES 中,索引在不同的特定条件下可以表示三种不同的意思:
* 表示源文件数据:当做数据的载体,即类比为数据表,通常称作 index 。例如:通常说 集群中有 product 索引,即表述当前 ES 的服务中存储了 product 这样一张"表"。
* 表示索引文件:以加速查询检索为目的而设计和创建的数据文件,通常承载于某些特定的数据结构,如哈希、FST 等。例如:通常所说的 正排索引 和 倒排索引(也叫正向索引和反向索引)。就是当前这个表述,索引文件和源数据是完全独立的,索引文件存在的目的仅仅是为了加快数据的检索,不会对源数据造成任何影响,
* 表示创建数据的动作:通常说创建或添加一条数据,在 ES 的表述为索引一条数据或索引一条文档,或者 index 一个 doc 进去。此时索引一条文档的含义为向索引中添加数据。
**索引的组成部分:**
* alias:索引别名
* settings:索引设置,常见设置如分片和副本的数量等。
* mapping:映射,定义了索引中包含哪些字段,以及字段的类型、长度、分词器等。

#### 3)类型:Type(ES 7.x 之后版本已删除此概念)
在较早的ES版本中,索引可以包含多个类型,每个类型代表了不同的文档结构。然而,从ES 7.x版本开始,类型已经被弃用,一个索引只能包含一个文档类型。
**ES 7.x**
* 不推荐在请求中指定类型。例如,索引文档不再需要文档type。新的索引 API 适用PUT {index}/_doc/{id}于显式 ID 和POST {index}/_doc 自动生成的 ID。请注意,在 7.0 中,_doc是路径的永久部分,表示端点名称而不是文档类型。
* 索引创建、索引模板和映射 API 中的include_type_name参数将默认为false. 完全设置参数将导致弃用警告。
* _default_映射类型被删除 。
**ES 8.x**
* 不再支持在请求中指定类型。
* 该include_type_name参数被删除。
#### 4)文档:Document
文档是ES中的最小数据单元。它是一个具有结构化JSON格式的记录。文档可以被索引并进行搜索、更新和删除操作。

文档元数据,所有字段均以下划线开头,为系统字段,用于标注文档的相关信息:
* _index:文档所属的索引名
* _type:文档所属的类型名
* _id:文档唯一id
* _source: 文档的原始Json数据
* _version: 文档的版本号,修改删除操作_version都会自增1
* _seq_no: 和_version一样,一旦数据发生更改,数据也一直是累计的。Shard级别严格递增,保证后写入的Doc的_seq_no大于先写入的Doc的_seq_no。
* _primary_term: _primary_term主要是用来恢复数据时处理当多个文档的_seq_no一样时的冲突,避免Primary Shard上的写入被覆盖。每当Primary Shard发生重新分配时,比如重启,Primary选举等,_primary_term会递增1。
### 2、ElasticSearch索引操作
参考文档:[Elasticsearch Guide \[7.17\] \| Elastic](https://www.elastic.co/guide/en/elasticsearch/reference/7.17/index.html "Elasticsearch Guide [7.17] | Elastic")
**创建索引**
格式: PUT /索引名称
索引命名规范:
* 以小写英文字母命名索引
* 不要使用驼峰命名法则
* 如过出现多个单词的索引名称,以全小写 + 下划线分隔的方式:如test_index。
ES 索引创建成功之后,以下属性将不可修改
* 索引名称
* 主分片数量
* 字段类型
#创建索引 PUT /es_db

#### 1)查询索引
格式: GET /索引名称
#查询索引
GET /es_db
#es_db是否存在
HEAD /es_db

#### 2)删除索引
格式: DELETE /索引名称
DELETE /es_db
#### 3)设置 Settings
创建索引的时候指定 settings
PUT