1. 全文检索
1.1 数据及检索分类
- 数据分类:
- 结构化数据: 固定格式、有限长度,比如mysql存的数据;
- 非结构化数据:不定长、无固定格式,比如邮件、word文档、日志;
- 半结构化数据:前两者结合,比如xml、html;
- 搜索分类:
- 结构化数据搜索: 使用关系型数据库
- 非结构化数据搜索
- 全文检索
- 顺序扫描
设想一个关于搜索的场景,假设我们要搜索一首诗句内容中带“前”字的古诗,如下:
name |
content |
author |
静夜思 |
床前明月光,疑是地上霜。举头望明月,低头思故乡。 |
李白 |
望庐山瀑布 |
日照香炉生紫烟,遥看瀑布挂前川。飞流直下三千尺,疑是银河落九天。 |
李白 |
... |
... |
... |
思考:用传统关系型数据库和ES实现会有什么差别?
如果用像 MySQL 这样的 RDBMS 来存储古诗的话,我们应该会去使用这样的 SQL 去查询:
select name from poems where content like "%前%"
这种我们称为顺序扫描法,需要遍历所有的记录进行匹配。不但效率低,而且不符合我们搜索时的期望,比如我们在搜索“ABCD"这样的关键词时,通常还希望看到"A","AB","CD",“ABC”的搜索结果。
1.2 什么是全文检索
全文检索是指:
- 通过一个程序扫描文本中的每一个单词,针对单词建立索引,并保存该单词在文本中的位置、以及出现的次数;
- 用户查询时,通过之前建立好的索引来查询,将索引中单词对应的文本位置、出现的次数返回给用户,因为有了具体文本的位置,所以就可以将具体内容读取出来了。
搜索原理可以简单概括为以下几步:
- 内容爬取,停顿词过滤比如一些无用的像"的",“了”之类的语气词/连接词;
- 内容分词,提取关键词;
- 根据关键词建立倒排索引
- 用户输入关键词进行搜索
1.3 倒排索引
索引就类似于目录,平时我们使用的都是索引,都是通过主键定位到某条数据,那么倒排索引呢,刚好相反,数据对应到主键。
- 正排索引(正向索引)
文章ID |
文章标题 |
文章内容 |
1 |
浅析JAVA设计模式 |
JAVA设计模式是每一个JAVA程序员都应该掌握的进阶知识 |
2 |
JAVA多线程设计模式 |
JAVA多线程与设计模式结合 |
- 倒排索引(反向索引)
假如,我们有一个站内搜索的功能,通过某个关键词来搜索相关的文章,那么这个关键词可能出现在标题中,也可能出现在文章内容中,那我们将会在创建或修改文章的时候,建立一个关键词与文章的对应关系表,这种,我们可以称之为倒排索引。
关键词 |
文章ID |
JAVA |
1,2 |
设计模式 |
1,2 |
多线程 |
2 |
简单理解,正向索引是通过key找value,反向索引则是通过value找key;ES底层在检索时底层使用的就是倒排索引。
2. ElasticSearch简介
2.1 ElasticSearch是什么
ElasticSearch(简称ES)是一个分布式、RESTful 风格的搜索和数据分析引擎,是用Java开发并且是当前最流行的开源的企业级搜索引擎,能够达到近实时搜索,稳定,可靠,快速,安装使用方便。客户端支持Java、.NET(C#)、PHP、Python、Ruby等多种语言。
官方网站: Elasticsearch Platform — Find real-time answers at scale | Elastic
下载地址:https://www.elastic.co/cn/downloads/past-releases#elasticsearch
- 搜索引擎排名:
参考网站:DB-Engines Ranking - popularity ranking of search engines
2.1.1 起源-Lucene
- 基于Java语言开发的搜索引擎库类
- 创建于1999年,2005年成为Apache 顶级开源项目
- Lucene具有高性能、易扩展的优点
- Lucene的局限性︰
- 只能基于Java语言开发
- 类库的接口学习曲线陡峭
- 原生并不支持水平扩展
2.1.2 Elasticsearch的诞生
Elasticsearch是构建在Apache Lucene之上的开源分布式搜索引擎。
- 2004年 Shay Banon 基于Lucene开发了Compass
- 2010年 Shay Banon重写了Compass,取名Elasticsearch
- 支持分布式,可水平扩展
- 降低全文检索的学习曲线,可以被任何编程语言调用
Elasticsearch 与 Lucene 核心库竞争的优势在于:
- 完美封装了 Lucene 核心库,设计了友好的 Restful-API,开发者无需过多关注底层机制,直接开箱即用。
- 分片与副本机制,直接解决了集群下性能与高可用问题。
2.2 Elastic Stack生态圈
在Elastic Stack之前我们听说过ELK,ELK分别是Elasticsearch、Logstash、Kibana这三款软件在一起的简称,在发展的过程中又有新的成员Beats的加入,就形成了Elastic Stack生态圈。
在Elastic Stack生态圈中Elasticsearch作为数据存储和搜索的中间件,是生态圈的基石,Kibana在上层提供用户一个可视化及操作的界面,Logstash和Beat可以对数据进行收集。在上图的右侧X-Pack部分则是Elastic公司提供的商业项目。
- 指标分析/日志分析
2.3 ElasticSearch应用场景
- 站内搜索
- 日志管理与分析
- 大数据分析
- 应用性能监控
- 机器学习
除了搜索之外,结合Kibana、Logstash、Beats,Elastic Stack还被广泛运用在大数据近实时分析领域,包括日志分析、指标监控、信息安全等多个领域。它可以帮助你探索海量结构化、非结构化数据,按需创建可视化报表,对监控数据设置报警阈值,甚至通过使用机器学习技术,自动识别异常状况。
- 通用数据处理流程:
3. ElasticSearch快速开始
3.1 ElasticSearch安装运行
3.1.1 环境准备
- 运行Elasticsearch需安装并配置JDK
- 设置$JAVA_HOME
- 可以参考ES的环境文件bin/elasticsearch-env.bat(如下图)
- ES的JDK环境生效的优先级配置ES_JAVA_HOME>JAVA_HOME>ES_HOME
- 各个版本对Java的依赖
- 查询网址:Support Matrix | Elastic
- Elasticsearch 5需要Java 8以上的版本
- Elasticsearch 从6.5开始支持Java 11
- 7.0开始,内置了Java环境
- ES比较耗内存,建议虚拟机4G或以上内存,JVM1G以上的内存分配。
3.1.2 下载并解压
下载地址: https://www.elastic.co/cn/downloads/past-releases#elasticsearch
3.1.2.1 安装包目录结构
目录 |
描述 |
bin |
脚本文件,包括启动elasticsearch,安装插件,运行统计数据等。 |
config |
配置文件目录,如elasticsearch配置、角色配置、jvm配置等。 |
jdk |
java运行环境 |
data |
默认的数据存放目录,包含节点、分片、索引、文档的所有数据,生产环境需要修改。 |
lib |
elasticsearch依赖的Java类库 |
logs |
默认的日志文件存储路径,生产环境需要修改。 |
modules |
包含所有的Elasticsearch模块,如Cluster、Discovery、Indices等。 |
plugins |
已安装插件目录 |
3.1.2.2 主配置文件
文件路径:elasticsearch\config\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配置项移除,重启集群或者将新节点加入某个已存在的集群时切记不要设置该配置项。
3.1.3 Linux环境安装
第一步:下载并解压安装包
tar -xzf elasticsearch-7.17.3-linux-x86_64.tar.gz
第二步:创建专用账户
#为elaticsearch创建用户并赋予相应权限
adduser es
passwd es
chown -R es:es elasticsearch-17.3
注意:ES不允许使用root账号启动服务,如果你当前账号是root,则需要创建一个专有账户。
第三步:配置环境变量
切换至ES用户,vi ~/.bash_profile,加入以下内容,并执行source ~/.bash_profile让环境变量生效。
export ES_JAVA_HOME=/安装路径/elasticsearch-7.17.3/jdk
第四步:开启远程访问
修改config/elasticsearch.yml配置文件
#ES开启远程访问
network.host: 0.0.0.0
第五步:修改JVM配置
修改config/jvm.options配置文件,调整jvm堆内存大小。
# vim jvm.options
-Xms1g
-Xmx1g
3.1.4 启动ElasticSearch服务
3.1.4.1 Windows环境
直接DOS窗口运行elasticsearch.bat
3.1.4.2 Linux(centos7)环境
ES不允许使用root账号启动服务,需要切换至新建的专用账户。
# -d 后台启动
bin/elasticsearch -d
访问:http://xxx.xxx.x.xxx:9200/
3.1.5 客户端Kibana安装
Kibana是一个开源分析和可视化平台,旨在与Elasticsearch协同工作。
3.1.5.1 下载并解压缩Kibana
下载地址:https://www.elastic.co/cn/downloads/past-releases#kibana
3.1.5.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.1.5.2 运行Kibana
注意:kibana也需要非root用户启动
#后台启动
nohup bin/kibana &
#查询kibana进程
netstat -tunlp | grep 5601
访问Kibana: http://xxx.xxx.x.xxx:5601/
若启动报错 kibana Error: listen EADDRNOTAVAIL: address not available x.x.x.x:5601
修改 server.host: x.x.x.x(服务器ip地址)为 server.host: 0.0.0.0
3.1.6 Elasticsearch安装分词插件
Elasticsearch提供插件机制对系统进行扩展,以安装analysis-icu这个分词插件为例;
3.1.6.1 在线安装
#查看已安装插件
bin/elasticsearch-plugin list
#安装插件
bin/elasticsearch-plugin install analysis-icu
#删除插件
bin/elasticsearch-plugin remove analysis-icu
3.1.6.2 离线安装
本地下载相应的插件,解压,然后手动上传到elasticsearch的plugins目录,然后重启ES实例就可以了。
比如ik中文分词插件:https://github.com/medcl/elasticsearch-analysis-ik
3.2 ElasticSearch基本概念
3.2.1 关系型数据库 vs ElasticSearch
- 在7.0之前,一个 Index可以设置多个Types;
- 目前Type已经被Deprecated,7.0开始,一个索引只能创建一个Type - “_doc”;
- 传统关系型数据库和Elasticsearch的区别:
- Elasticsearch- Schemaless /相关性/高性能全文检索
- RDMS —事务性/ Join
关系型数据库 |
ElasticSearch |
Database(数据库) |
Index(索引库) |
Table(表) |
Type(类型) |
Row(行) |
Document(文档) |
Column(列) |
Field(字段) |
3.2.2 索引(Index)
一个索引就是一个拥有几分相似特征的文档的集合。比如说,可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。
3.2.3 文档(Document)
- Elasticsearch是面向文档的,文档是所有可搜索数据的最小单位;
- 日志文件中的日志项
- 一本电影的具体信息/一张唱片的详细信息
- MP3播放器里的一首歌/一篇PDF文档中的具体内容
- 文档会被序列化成JSON格式,保存在Elasticsearch中;
- JSON对象由字段组成
- 每个字段都有对应的字段类型(字符串/数值/布尔/日期/二进制/范围类型)
- 每个文档都有一个Unique ID
- 可以自己指定ID或者通过Elasticsearch自动生成
- 一篇文档包含了一系列字段,类似数据库表中的一条记录;
- JSON文档,格式灵活,不需要预先定义格式;
- 字段的类型可以指定或者通过Elasticsearch自动推算
- 支持数组/支持嵌套
3.2.3.1 文档元数据
元数据,用于标注文档的相关信息:
- _index:文档所属的索引名
- _type:文档所属的类型名
- _id:文档唯—ld
- _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。
3.3 ElasticSearch索引操作
参考文档:Elasticsearch Guide [7.17] | Elastic文章来源:https://www.toymoban.com/news/detail-808608.html
3.3.1 创建索引
索引命名必须小写,不能以下划线开头文章来源地址https://www.toymoban.com/news/detail-808608.html
- 格式: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
}
}
3.3.2 查询索引
- 格式:GET /索引名称
#查询索引
GET /es_db
#es_db是否存在
HEAD /es_db
3.3.3 删除索引
- 格式:DELETE /索引名称
DELETE /es_db
3.4 ElasticSearch文档操作
3.4.1 添加文档
- 格式:[PUT | POST] /索引名称/[_doc | _create ]/id
- 创建文档,指定id。
- 注意:POST和PUT都能起到创建/更新的作用,PUT需要对一个具体的资源进行操作也就是要确定id才能进行更新/创建,而POST是可以针对整个资源集合进行操作的,如果不写id就由ES生成一个唯一id进行创建新文档,如果填了id那就针对这个id的文档进行创建/更新。
- _create:如果ID已经存在则会失败
# 创建文档,指定id;
# 如果id不存在,创建新的文档;否则先删除现有文档,再创建新的文档,版本会增加。
PUT /es_db/_doc/1
{
"name": "张三",
"sex": 1,
"age": 25,
"address": "天河公园",
"remark": "java developer"
}
#创建文档,ES生成id
POST /es_db/_doc
{
"name": "张三",
"sex": 1,
"age": 25,
"address": "文化公园",
"remark": "java developer"
}
3.4.2 修改文档
3.4.2.1 全量更新
- 使用_doc全量更新,整个json都会替换;
- 格式:[PUT | POST] /索引名称/_doc/id
- 如果文档存在,现有文档会被删除,新的文档会被索引。
#查询文档
GET /es_db/_doc/2
# 全量更新,替换整个json。
PUT /es_db/_doc/2
{
"name": "唐三",
"sex": 1,
"age": 25,
"address": "广州天河公园",
"remark": "投资"
}
3.4.2.2 部分更新
- 使用_update部分更新
- 格式:POST /索引名称/_update/id
- update不会删除原来的文档,而是实现真正的数据更新。
# 部分更新:在原有文档上更新
# Update -文档必须已经存在,更新只会对相应字段做增量修改
POST /es_db/_update/1
{
"doc": {
"age": 28
}
}
#查询文档
GET /es_db/_doc/1
- 使用 _update_by_query 更新文档(根据条件更新)
POST /es_db/_update_by_query { "query": { "match": { "_id": 1 } }, "script": { "source": "ctx._source.age = 30" } }
3.4.5 删除文档
- 格式:DELETE /索引名称/_doc/id
DELETE /es_db/_doc/1
到了这里,关于ElasticSearch快速入门的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!