引言:
本文主要分享了有关Elasticsearch(简称ES)的知识,包括:ES的简介、基本概念、倒序索引、ES的安装以及使用、Kibana可视化工具的安装与使用、分词的使用、使用可视化工具Kibana实现索引和文档的增删查改、以及一些高级的ES查询,如:批量获取文档信息、使用Bulk API实现批量操作、采用乐观锁机制实现并发控制、Mapping、通用查询(分词查找、短语查询、返回指定字段、高亮查询、范围查询 )、Bool过滤查询、范围查询、聚合查询等等;
Elasticsearch 是一个开源的搜索引擎, 建立在全文搜索引擎库 Apache Lucene 基础上;内部使用 Lucene 做索引与搜索,但是它的目的是使全文检索变得简单,通过隐藏 Lucene 的复杂性,取而代之的提供一套简单一致的 RESTFUL API;
Elasticsearch 不仅仅只是一个全文搜索引擎是一个分布式的实时文档存储,每个字段可以被索引与搜索可以作数据库用;还是一个分布式实时分析搜索引擎,能胜任上百个服务节点的扩展,并支持PB级别(大数据级别)的结构化(定死的,进去多少出来多少,多余的全部抛弃)或者非结构化数据(只需要直到其属性即可);
Near Realtime(NRT) 近实时:数据提交索引后,立马就可以搜索到。
Cluster 集群:一个集群由一个唯一的名字标识,默认为“elasticsearch”。集群名称非常重要,具有相同集群名的节点才会组成一个集群。集群名称可以在配置文件中指定。
Node 节点:存储集群的数据,参与集群的索引和搜索功能。像集群有名字,节点也有自己的名称,默认在启动时会以一个随机的UUID的前七个字符作为节点的名字,你可以为其指定任意的名字。通过集群名在网络中发现同伴组成集群。一个节点也可是集群。
Index 索引:一个索引是一个文档的集合(等同于solr中的集合)。每个索引有唯一的名字,通过这个名字来操作它。一个集群中可以有任意多个索引。Type 类型:指在一个索引中,可以索引不同类型的文档,如用户数据、博客数据。从6.0.0 版本起已废弃,一个索引中只存放一类数据。
Document 文档:被索引的一条数据,索引的基本信息单元,以JSON格式来表示。
Shard 分片:在创建一个索引时可以指定分成多少个分片来存储。每个分片本身也是一个功能完善且独立的“索引”,可以被放置在集群的任意节点上。分片的好处:允许我们水平切分/扩展容量、可在多个分片上进行分布式的、并行的操作,提高系统的性能和吞吐量。
注意:分片数创建索引时指定,创建后不可改了。备份数可以随时改。
Replication 备份: 一个分片可以有多个备份(副本)。备份的好处:高可用。一个主分片挂了,副本分片就顶上去 扩展搜索的并发能力、吞吐量。搜索可以在所有的副本上并行运行。-高并发下副本也可搜索
平时的数据可以分为结构化数据和非结构化数据:
结构化数据是指格式和长度固定的数据,如一个人的年龄,姓名等;非结构化数据是指格式和长度不固定的数据,如一个文章的内容等;对于结构化数据,可以存储在DB中通过精确匹配找到。但是对于非结构化数据,一般查询时只能提供查询的局部信息或模糊信息,传统数据库无法根据这些信息进行查询,效率差;
倒排索引是相对于正排索引而言的,可以有效的解决该问题;
正排索引可以通过id查找到对应的文章,但是无法通过给的部分内容如elasticsearch,找出含有该关键字的文档。
倒排索引会先对文档进行分析将其拆分成单个Term, 并存储包含该Term的文档id,这样便可以实现通过内容查找对应文档,如包含elasticsearch的文档为文档1;
倒排索引的过程:
通过倒排索引获得“搜索引擎”对应的文档id列表,有1和3;通过正排索引查询1和3的完整内容;返回最终结果;官网下载地址: https://www.elastic.co/downloads/elasticsearch
推荐到华为云镜像下载:https://mirrors.huaweicloud.com/
JDK版本: 1.8
解压安装包,进入bin目录中双击elasticsearch.bat等待启动完毕;
打开浏览器,输入 http://localhost:9200 出现以下画面,说明ES安装成功;
Kibana是一个针对Elasticsearch的开源分析及可视化平台,使用Kibana可以查询、查看并与存储在ES索引的数据进行交互操作,同时也能执行高级的数据分析,并能以图表、表格和地图的形式查看数据 ;
下载安装包,需要和ES版本匹配,下载完毕后安装到相应的目录就行;
下载地址:https://www.elastic.co/downloads/kibana
在目录config/kibana.yml中配置 elasticsearch.hosts: 的值为ES的访问地址;
双击bin/kibana.bat
访问地址:http://localhost:5601IK Analyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包;从3.0版本开始,IK发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。在2012版本中,IK实现了简单的分词歧义排除算法,标志着IK分词器从单纯的词典分词向模拟语义分词衍化;
获取 ES-IKAnalyzer插件,需要和ES版本一致;
将ik的压缩包解压到 ES安装目录的plugins/目录下(新建文件夹analysis-ik),重启ES;
下载地址: https://github.com/medcl/elasticsearch-analysis-ik/releases
Ik分词器有ik_max_word和ik_smart两种模式:
ik_max_word:会将文本做最细粒度的拆分;ik_smart:会做最粗粒度的拆分;首先在IKAnalyzer.cfg.xml里面定义自定义的字典,我这里是main.dic(自己随意命名);
<?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">main.dic</entry> <!--用户可以在这里配置自己的扩展停止词字典--> <entry key="ext_stopwords"></entry> <!--用户可以在这里配置远程扩展字典 --> <!-- <entry key="remote_ext_dict">words_location</entry> --> <!--用户可以在这里配置远程扩展停止词字典--> <!-- <entry key="remote_ext_stopwords">words_location</entry> --> </properties>PUT方法:存在就修改,不存在就新增;
PUT /kak/student/1 { "name":"kaka", "sex":"man", "age":23, "score":150 }创建索引、添加文档
PUT kak_01 PUT kak_01/student/1 { "name":"kaka", "age":23, "sex":"man" } PUT kak_01/student/2 { "name":"zhuangzhuang", "age":23, "sex":"woman" } PUT kak_02 PUT kak_02/student/1 { "name":"zhangsan", "age":23, "sex":"man" } PUT kak_02/student/2 { "name":"lisi", "age":23, "sex":"woman" }}
语法格式:
{action:{metadata}}
{requstbody}
action:(行为)
create:文档不存在时创建update:更新文档index:创建新文档或替换已有文档delete:删除一个文档create 和index的区别:
如果数据存在,使用create操作失败,会提示文档已经存在;如果数据存在,使用index则可以成功执行;操作的大小建议:
Bulk会把将要处理的数据载入内存中,所以数据量是有限制的,最佳的数据量不是一个确定的数值取决于硬件;
一般建议是1000-5000个文档,大小建议是5-15MB,默认不能超过100M,可以在ES的配置文件($ES_HOME下的config下的elasticsearch.yml)中设置;ElasticSearch采用了乐观锁来保证数据的一致性,当用户对document进行操作时,并不需要对该document作加锁和解锁的操作,只需要指定要操作的版本;当版本号一致时,ElasticSearch会允许该操作顺利执行,当版本号存在冲突时,ElasticSearch会提示冲突并抛出异常(VersionConflictEngineException异常);
ElasticSearch的版本号的取值范围为1到2^63-1。使用的是_version(每修改一个版本加一)Elasticsearch在处理外部版本号时会与对内部版本号的处理有些不同。它不再是检查version是否与请求中指定的数值相同,而是检查当前的version是否比指定的数值小。如果请求成功,那么外部的版本号就会被存储到文档中的version中。为了保持version与外部版本控制的数据一致使用version_type=external ;
查看自动生成的映射情况
GET kak_01/_mapping 1核心数据类型:
字符型:string
string类型包括,text 和 keyword
text类型被用来索引长文本,在建立索引前会将这些文本进行分词,转化为词的组合,建立索引。允许es来检索这些词语。text类型不能用来排序和聚合。Keyword类型不需要进行分词,可以被用来检索过滤、排序和聚合。keyword 类型字段只能用本身来进行检索数字型:long, integer, short, byte, double, float
日期型:date
布尔型:boolean
二进制型:binary
关键的属性:
“index”: true分词,false不分词,设置成false,字段将不会被索引;
“analyzer”:"ik"指定分词器,默认分词器为standard analyzer
PUT /lib { "settings":{ "number_of_shards" : 3, "number_of_replicas" : 0 }, "mappings":{ "properties":{ "title":{"type":"text"}, "name":{"type":"text","analyzer":"standard"}, "publish_date":{"type":"date","index":false}, "price":{"type":"double"} } } } 定义Mapping没有类型,之前能写进去是因为通过PUT,放文档放进去的;PUT /lib2/_doc/2 { “name” : “taotao”, “address” : “sz”, “age” : 33, “interests” : “java,music,money”, “birthday”: “1983-08-08” }
PUT /lib2/_doc/2 { “name” : “taotao”, “address” : “sz”, “age” : 33, “interests” : “java,music,money”, “birthday”: “1983-08-08” }
term查询
match query知道分词器的存在,会对filed进行分词操作,然后再查询
GET /lib2/_search { "query": { "match": { "name": "kak helloworld" } } }ElasticSearch引擎首先分析查询字符串,从分析后的文本中构建短语查询,这意味着必须匹配短语中的所有分词,并且保证各个分词的相对位置不变
GET /lib2/_search { "query": { "match_phrase": { "interests": "java,music" } } }允许使用通配符* 和 ?来进行查询:
*代表0个或多个字符?代表任意一个字符 GET /lib2/_search { "query": { "wildcard": { "name": "kak*" } } }sum:求和
GET /lib2/_search { "size": 0, "aggs": { "agesum": { "sum": { "field": "age" } } } }min:最小值
GET /lib2/_search { "size": 0, "aggs": { "agemin": { "min": { "field": "age" } } } }