全文检索
数据分类:
1、结构化数据: 固定格式,有限长度 比如mysql存的数据
2、非结构化数据:不定长,无固定格式 比如邮件,word文档,日志
3、半结构化数据: 前两者结合 比如xml,html
搜索分类:
1、结构化数据搜索: 使用关系型数据库
2、非结构化数据搜索
2.1 顺序扫描
2.2 全文检索
设想一个关于搜索的场景,假设我们要搜索一首诗句内容中带“前”字的古
思考:用传统关系型数据库和ES 实现会有什么差别?
如果用像 MySQL 这样的 RDBMS 来存储古诗的话,我们应该会去使用这样的 SQL 去查询
select name from poems where content like "%前%"
这种我们称为顺序扫描法,需要遍历所有的记录进行匹配。不但效率低,而且不符合我们搜 索时的期望,比如我们在搜索“ABCD"这样的关键词时,通常还希望看 到"A","AB","CD",“ABC”的搜索结果。
什么是全文检索
全文检索是指:
1、通过一个程序扫描文本中的每一个单词,针对单词建立索引,并保存该单词在文 本中的位置、以及出现的次数
2、用户查询时,通过之前建立好的索引来查询,将索引中单词对应的文本位置、出现的次数返回给用户,因为有了具体文本的位置,所以就可以将具体内容读取出来了
搜索原理简单概括的话可以分为这么几步:
1、内容爬取,停顿词过滤比如一些无用的像"的",“了”之类的语气词/连接词
2、内容分词,提取关键词
3、根据关键词建立倒排索引
4、用户输入关键词进行搜索
倒排索引
索引就类似于目录,平时我们使用的都是索引,都是通过主键定位到某条数据, 那么倒排索引呢,刚好相反, 数据对应到主键。
这里以一个博客文章的内容为例:
倒排索引(反向索引)
假如,我们有一个站内搜索的功能,通过某个关键词来搜索相关的文章,那么这个关键词可 能出现在标题中,也可能出现在文章内容中,那我们将会在创建或修改文章的时候,建立一 个关键词与文章的对应关系表,这种,我们可以称之为倒排索引。
like %java设计模式% java 设计模式
简单理解,正向索引是通过key找value,反向索引则是通过value找key。ES底层在检索时 底层使用的就是倒排索引。
ElasticSearch简介
ElasticSearch是什么
ElasticSearch(简称ES)是一个分布式、RESTful 风格的搜索和数据分析引擎 , 是用Java 开发并且是当前最流行的开源的企业级搜索引擎,能够达到近实时搜索 ,稳定,可靠,快 速,安装使用方便。
客户端支持Java、.NET(C#)、PHP、Python、Ruby等多种语言。
官方网站: https://www.elastic.co/
下载地址: https://www.elastic.co/cn/downloads/past-releases#elasticsearch
搜索引擎排名:
起源——Lucene
1、基于Java语言开发的搜索引擎库类
2、创建于1999年,2005年成为Apache 顶级开源项目
3、Lucene具有高性能、易扩展的优点
4、Lucene的局限性︰
4.1 只能基于Java语言开发
4.2 类库的接口学习曲线陡峭
4.3 原生并不支持水平扩展
Elasticsearch的诞生
Elasticsearch是构建在Apache Lucene之上的开源分布式搜索引擎。
1、2004年 Shay Banon 基于Lucene开发了Compass
2、2010年 Shay Banon重写了Compass,取名Elasticsearch
2.1 支持分布式,可水平扩展
2.2 降低全文检索的学习曲线,可以被任何编程语言调用
Elasticsearch 与 Lucene 核心库竞争的优势在于:
1、完美封装了 Lucene 核心库,设计了友好的 Restful-API,开发者无需过多关注 底层机制,直接开箱即用。
2、分片与副本机制,直接解决了集群下性能与高可用问题。
ES Server进程 3节点 raft (奇数节点) 数据分片 -》lucene实例 分片和副本数 1个ES节点可以有多个lucene实例。也可以指定 一个索引的多个分片
ElasticSearch vs Solr
Solr 是第一个基于 Lucene 核心库功能完备的搜索引擎产品,诞生远早于 Elasticsearch。 当单纯的对已有数据进行搜索时,Solr更快。当实时建立索引时, Solr会产生io阻 塞,查询性能较差, Elasticsearch具有明显的优势。
1、Solr 利用 Zookeeper 进行分布式管理,而Elasticsearch 自身带有分布式协调 管理功能。
2、Solr 支持更多格式的数据,比如JSON、XML、CSV,而 Elasticsearch 仅支持 json文件格式。
3、Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效 率明显低于 Elasticsearch。
4、Solr 是传统搜索应用的有力解决方案,但 Elasticsearch更适用于新兴的实时搜 索应用。
Elastic Stack介绍
在Elastic Stack之前我们听说过ELK,ELK分别是Elasticsearch,Logstash,Kibana这 三款软件在一起的简称,在发展的过程中又有新的成员Beats的加入,就形成了Elastic Stack。
在Elastic Stack生态圈中Elasticsearch作为数据存储和搜索,是生态圈的基石,Kibana在 上层提供用户一个可视化及操作的界面,Logstash和Beat可以对数据进行收集。在上图的 右侧X-Pack部分则是Elastic公司提供的商业项目。
ElasticSearch应用场景
1、站内搜索
2、日志管理与分析
3、大数据分析
4、应用性能监控
5、机器学习
国内现在有大量的公司都在使用 Elasticsearch,包括携程、滴滴、今日头条、饿了么、 360安全、小米、vivo等诸多知名公司。除了搜索之外,结合Kibana、Logstash、Beats, Elastic Stack还被广泛运用在大数据近实时分析领域,包括日志分析、指标监控、信息安全 等多个领域。它可以帮助你探索海量结构化、非结构化数据,按需创建可视化报表,对监控 数据设置报警阈值,甚至通过使用机器学习技术,自动识别异常状况。
通用数据处理流程:
ElasticSearch快速开始
ElasticSearch安装运行
环境准备
运行Elasticsearch,需安装并配置JDK
设置$JAVA_HOME
各个版本对Java的依赖 https://www.elastic.co/support/matrix#matrix_jvm
Elasticsearch 5需要Java 8以上的版本
Elasticsearch 从6.5开始支持Java 11
7.0开始,内置了Java环境
ES比较耗内存,建议虚拟机4G或以上内存,jvm1g以上的内存分配
可以参考es的环境文件elasticsearch-env.bat
ES的jdk环境生效的优先级配置ES_JAVA_HOME>JAVA_HOME>ES_HOME
下载并解压ElasticSearch
下载地址: https://www.elastic.co/cn/downloads/past-releases#elasticsearch
选择版本:7.17.3
ElasticSearch文件目录结构
目录 | 描述 |
bin | 脚本文件,包括启动elasticsearch,安装插件,运行统计数据等 |
config | 配置文件目录,如elasticsearch配置、角色配置、jvm配置等。 |
jdk | java运行环境 |
data | 默认的数据存放目录,包含节点、分片、索引、文档的所有数 据,生产环境需要修改。 |
lib | elasticsearch依赖的Java类库 |
logs | 默认的日志文件存储路径,生产环境需要修改。 |
modules | 包含所有的Elasticsearch模块,如Cluster、Discovery、 Indices等。 |
plugins | 已安装插件目录 |
主配置文件elasticsearch.yml
cluster.name
当前节点所属集群名称,多个节点如果要组成同一个集群,那么集群名称一定要配置成相同。默认值elasticsearch,生产环境建议根据ES集群的使用目的修改成合适的名字。
node.name
当前节点名称,默认值当前节点部署所在机器的主机名,所以如果一台机器上要起多个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
配置能够访问当前节点的主机,默认值为当前节点所在机器的本机回环地址127.0.0.1 和 [::1],这就导致默认情况下只能通过当前节点所在主机访问当前节点。 可以配置为 0.0.0.0 ,表示所有主机均可访问。
http.port
配置当前ES节点对外提供服务的http端口,默认值 9200
discovery.seed_hosts
配置参与集群节点发现过程的主机列表,说白一点就是集群中所有节点所在的主机列表,可以是具体的IP地址,也可以是可解析的域名。
cluster.initial_master_nodes
配置ES集群初始化时参与master选举的节点名称列表,必须与node.name配置的一致。ES集群首次构建完成后,应该将集群中所有节点的配置文件中的 cluster.initial_master_nodes配置项移除,重启集群或者将新节点加入某个已存在的集群时切记不要设置该配置项。
# ES 开启远程访问
network . host : 0.0.0.0
修改JVM配置
修改config/jvm.options配置文件,调整jvm堆内存大小
vim jvm . options
‐ Xms4g
‐ Xmx4g
配置的建议
Xms和Xms设置成—样
Xmx不要超过机器内存的50%
不要超过30GB - https://www.elastic.co/cn/blog/a-heap-of-trouble
启动ElasticSearch服务
Windows
直接运行elasticsearch.bat
Linux(centos7)
ES不允许使用root账号启动服务,如果你当前账号是root,则需要创建一个专有账户
# 非 root 用户
bin / elasticsearch
‐ d 后台启动
bin / elasticsearch ‐ d
注意:es默认不能用root用户启动,生产环境建议为elasticsearch创建用户。
运行http://localhost:9200/
如果ES服务启动异常,会有提示:
启动ES服务常见错误解决方案
[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]ES因为需要大量的创建索引文件,需要大量的打开系统的文件,所以我们需要解除linux系统当中打开文件最大数目的限制,不然ES启动就会抛错
[2]: max number of threads [1024] for user [es] is too low, increase to at least [4096]
[3]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
最大虚拟内存太小,调大系统的虚拟内存
[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,生产环境必填
客户端Kibana安装
Kibana是一个开源分析和可视化平台,旨在与Elasticsearch协同工作。
1)下载并解压缩Kibana
下载地址: https://www.elastic.co/cn/downloads/past-releases#kibana
选择版本:7.17.3
2)修改Kibana.yml
vim config / kibana . yml
server . port : 5601
server . host : "localhost" # 服务器 ip
elasticsearch . hosts : [ "http://localhost:9200" ] #elasticsearch 的访问地址
i18n . locale : "zh‐CN" #Kibana 汉化
3)运行Kibana
注意:kibana也需要非root用户启动
1、 bin / kibana
2、 # 后台启动
3、 nohup bin / kibana &
访问Kibana: http://localhost:5601/
cat API
1、 / _cat / allocation # 查看单节点的 shard 分配整体情况
2、 / _cat / shards # 查看各 shard 的详细情况
3、 / _cat / shards / { index } # 查看指定分片的详细情况
4、 / _cat / master # 查看 master 节点信息
5、 / _cat / nodes # 查看所有节点信息
6、 / _cat / indices # 查看集群中所有 index 的详细信息
7、 / _cat / indices / { index } # 查看集群中指定 index 的详细信息
8、 / _cat / segments # 查看各 index 的 segment 详细信息 , 包括 segment 名 , 所属 shard , 内存 ( 磁盘 ) 占用大小 , 是否刷盘
9、 / _cat / segments / { index } # 查看指定 index 的 segment 详细信息
10、 / _cat / count # 查看当前集群的 doc 数量
11、 / _cat / count / { index } # 查看指定索引的 doc 数量
12、 / _cat / recovery # 查看集群内每个 shard 的 recovery 过程 . 调整 replica 。
13、 / _cat / recovery / { index } # 查看指定索引 shard 的 recovery 过程
14 、 / _cat / health # 查看集群当前状态:红、黄、绿
15、 / _cat / pending_tasks # 查看当前集群的 pending task
16、 / _cat / aliases # 查看集群中所有 alias 信息 , 路由配置等
17 、 / _cat / aliases / { alias } # 查看指定索引的 alias 信息
18、 / _cat / thread_pool # 查看集群各节点内部不同类型的 threadpool 的统计信息 ,
19、 / _cat / plugins # 查看集群各个节点上的 plugin 信息
20、 / _cat / fielddata # 查看当前集群各个节点的 fielddata 内存使用情况
21 、 / _cat / fielddata / { fields } # 查看指定 field 的内存使用情况 , 里面传 field 属性对应的 值
22 、 / _cat / nodeattrs # 查看单节点的自定义属性
23、 / _cat / repositories # 输出集群中注册快照存储库
24 、 / _cat / templates # 输出当前正在存在的模板信息
Elasticsearch安装分词插件
Elasticsearch提供插件机制对系统进行扩展
以安装analysis-icu这个 分词 插件为例
在线安装
#查看已安装插件bin/elasticsearch‐plugin list#安装插件bin/elasticsearch‐plugin install analysis‐icu#删除插件bin/elasticsearch‐plugin remove analysis‐icu
注意:安装和删除完插件后,需要重启ES服务才能生效。
测试分词效果
POST _analyze
{"analyzer":"icu_analyzer","text":"中华人民共和国"}
离线安装
本地下载相应的插件,解压,然后手动上传到elasticsearch的plugins目录,然后重启ES实 例就可以了。
比如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":"中华人民共和国"}
创建索引时可以指定IK分词器作为默认分词器
PUT /es_db{"settings" : {"index" : {"analysis.analyzer.default.type": "ik_max_word"}}
}
ElasticSearch基本概念
关系型数据库 VS ElasticSearch
1、在7.0之前,一个 Index可以设置多个Types
2、目前Type已经被Deprecated,7.0开始,一个索引只能创建一个Type - “_doc”
3、传统关系型数据库和Elasticsearch的区别:
3.1 Elasticsearch- Schemaless /相关性/高性能全文检索
3.2 RDMS —事务性/ Join
索引(Index)
一个索引就是一个拥有几分相似特征的文档的集合。 比如说,可以有一个客户数据的索引, 另一个产品目录的索引,还有一个订单数据的索引。
一个索引由一个名字来标识(必须全部是小写字母的) ,并且当我们要对对应于这个索引中 的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。
文档(Document)
文档元数据
元数据,用于标注文档的相关信息:
1、_index:文档所属的索引名
2、_type:文档所属的类型名
3、_id:文档唯—ld
4、_source: 文档的原始Json数据
5、_version: 文档的版本号,修改删除操作_version都会自增1
6、_seq_no: 和_version一样, 一旦数据发生更改,数据也一直是累计的。 Shard级别严格递增,保证后写入的Doc的_seq_no大于先写入的Doc的_seq_no。
7、_primary_term: _primary_term主要是用来恢复数据时处理当多个文档的
8、_seq_no一样时的冲突,避免Primary Shard上的写入被覆盖。每当Primary Shard 发生重新分配时,比如重启,Primary选举等,_primary_term会递增1。
创建索引
索引命名必须小写,不能以下划线开头
格式: PUT /索引名称
#创建索引PUT /es_db#创建索引时可以设置分片数和副本数PUT /es_db{"settings" : {"number_of_shards" : 3,"number_of_replicas" : 2}}#修改索引配置PUT /es_db/_settings{"index" : {"number_of_replicas" : 1}}
查询索引
格式: GET /索引名称
#查询索引GET /es_db#es_db是否存在HEAD /es_db
删除索引
格式: DELETE /索引名称
DELETE /es_db
批量删除delete
POST _bulk{"delete":{"_index":"article", "_type":"_doc", "_id":3}}{"delete":{"_index":"article", "_type":"_doc", "_id":4}}
批量修改update
POST _bulk{"update":{"_index":"article", "_type":"_doc", "_id":3}}{"doc":{"title":"ES大法必修内功"}}{"update":{"_index":"article", "_type":"_doc", "_id":4}}{"doc":{"create_time":1554018421008}}
组合应用
POST _bulk{"create":{"_index":"article", "_type":"_doc", "_id":3}}{"id":3,"title":"fox老师","content":"fox老师666","tags":["java", "面向对
象"],"create_time":1554015482530}{"delete":{"_index":"article", "_type":"_doc", "_id":3}}{"update":{"_index":"article", "_type":"_doc", "_id":4}}{"doc":{"create_time":1554018421008}}
批量读取
es的批量查询可以使用mget和msearch两种。其中mget是需要我们知道它的 id,可以指定不同的index,也可以指定返回值source。msearch可以通过字段 查询来进行一个批量的查找。
_mget
#可以通过ID批量获取不同index和type的数据GET _mget{"docs": [{"_index": "es_db","_id": 1},{
"_index": "article",
"_id": 4
}
]
}#可以通过ID批量获取es_db的数据
GET /es_db/_mget
{
"docs": [
{
"_id": 1
},
{
"_id": 4
}
]
}
#简化后
GET /es_db/_mget
{
"ids":["1","2"]
}
_msearch
在_msearch中,请求格式和bulk类似。查询一条数据需要两个对象,第一个设置index和 type,第二个设置查询语句。查询语句和search相同。如果只是查询一个index,我们可以 在url中带上index,这样,如果查该index可以直接用空对象表示。
GET /es_db/_msearch
{}
{"query" : {"match_all" : {}}, "from" : 0, "size" : 2}{"index" : "article"}{"query" : {"match_all" : {}}}