ElasticSearch笔记

ElasticSearch笔记_第1张图片

Lucene 和 ElasticSearch 关系:ElasticSearch 是基于 Lucene 做了一些封装和增强。

ElasticSearch 概述

  • ElasticSearch,简称为es,es是一个开源的 高扩展分布式全文检索引擎,它可以近乎 实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别(大数据时代)的数据。es也使用java并发使用 Lucene 作为其核心来实现所有索引和搜索的功能,但是他的目的是通过简单的 Restful API 来隐藏Lucene 的复杂性,从而让全文搜索变得简单。

  • 据国际权威的数据库产品评测机构DB Engines 的统计,在2016年1月,ElasticSearch已超过Solr等,成为排名第一的搜索引擎类应用

历史

  • 多年前,一个叫做 Shay Banon的刚结婚不久的失业开发者,由于妻子要去伦敦学习厨师,他便跟着去了。在他找工作的过程中,为了给妻子构建一个食谱的搜索引擎,他开始构建一个早期版本的 Lucene。
  • 直接基于Lucene工作会比较困难。所以Shay开始抽象Lucene代码以便java程序员可以在应用中添加搜索功能。他发布了他的第一个开源项目,叫做 “Compass”。
  • 后来Shay找到一份工作,这份工作处在高性能和内存数据网格的分布式环境中,因此高性能的、实时的、分布式的搜索引擎也是理所当然需要的。然后他决定重写Compass库使其成为一个独立的服务叫做 ElasticSearch
  • 第一个公开版本出现的2010年2月,在那之后 ElasticSearch已经成为Github上最受欢迎的项目之一,代码贡献者超过300人。一家主营ElasticSearch的公司就此成立,他们一边提供商业支持一边开发新功能,不过ElasticSearch 将永远开源且对所有人可用。
  • Shay的妻子依旧等待着她的食谱搜索.....

哪些都在使用ElasticSearch:

1、维基百科,类似百度百科,全文检索,高亮,搜索推荐/2(权重,百度!)

2、The Guardian(国外新闻网站),类似搜狐新闻,用户行为日志(点击,浏览,收藏,评论)+社交网络数据(对某某新闻的相关看法),数据分析,给到每篇新闻文章的作者,让他知道他的文章的公众反馈(好,坏,热门,垃圾,鄙视,崇拜)

3、Stack Overflow(国外的程序异常讨论论坛),IT问题,程序的报错,提交上去,有人会跟你讨论和回答,全文检索,搜索相关的问题和答案,程序报错了,就会讲报错信息粘贴到里面去,搜索有没有对应的答案。

4、Github(开源代码管理),搜索上千亿行代码。

5、电商网站,检索商品。

6、日志数据分析,Logstash采集日志,ES进行复杂的数据分析,ELK技术 ,elasticsearch + logstash + kibana

7、商品价格监控网站,用户设定某商品的价格阈值,当低于该阈值的时候,发送通知消息给用户,比如说订阅牙膏的监控,如果高露洁牙膏的家庭套装低于50块钱,就通知我,然后就进行购买。

8、Bi系统,商业智能,Business Intelligence。比如说有个大型商场集团,BI,分析一下某某区域最近3年的用户消费金额的趋势已经用户群体的组成构成。产出相关的数张报表,**区,最近3年,每年消费金额呈现100%的增长,而且用户群体85%是高级白领,开一个新商场。ES执行数据分析和挖掘,Kibana进行数据可视化。

9、国内:站内搜索(电商,招聘,门户,等等),IT系统搜索(OA,CRM,ERP,等等),数据分析(ES热门的一个使用场景)

ES和solr的差别

ElasticSearch 简介

  • ElasticSearch是一个实时分布式搜索和分析引擎。它让你以前所未有的速度处理大数据成为可能。

  • 它用于 全文搜索结构化搜索分析以及将这三者混合使用:

  • 维基百科使用ElasticSearch提供全文搜索并高亮关键字,以及输入实时搜索(search-asyou-type)和搜索纠错(did-you-mean)等搜索建议功能。

  • 英国卫报使用 ElasticSearch结合用户日志和社交网络数据提供给他们的编辑以实时的反馈,以便及时了解公众对新发表的文章的回应。

  • StackOverflow结合全文搜索与地理位置查询,以及 more-like-this 功能来找到相关的问题和答案。

  • Github使用ElasticSearch检索1300亿行的代码。

  • 但是ElasticSearch不仅用于大型企业,它还让像DataDog以及Klout这样的创业公司将最初的想法变成可扩展的解决方案。

  • ElasticSearch可以在笔记本上运行,也可以在数以百计的服务器上处理PB级别的数据。

  • ElasticSearch是一个基于 Apache Lucene(TM)的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、型男最好、功能最全的搜索引擎库。

  • 但是,Lucene只是一个库。想要使用它,必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene非常复杂,需要深入了解检索的相关只是来理解它是如何工作的。

  • ElasticSearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的 Restful API 来隐藏 Lucene的复杂性,从而让全文搜索变得简单。

Solr简介

  • Solr 是Apache 下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器。Slor提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进行了优化。
  • Solr可以独立运行,运行在Jetty、Tomcat等这些Servlet容器中,Slor索引的实现方法很简单,用POST方法想 Solr 服务器发送一个描述 Field 及其内容的XML 文档,Solr根据xml文档添加、删除、更新索引。Solr搜索只需要发送 HTTP GET请求,然后对Solr返回Xml、json等格式的查询结果进行解析,组织页面布局,Solr不提供构建UI的功能,Solr提供了一个管理界面,通过管理界面可以查询Solr的配置和运行情况。
  • solr是基于 Lucene 开发企业级搜索服务器,实际上就是封装了 Lucene。
  • Solr是一个独立的企业级搜索应用服务器,它对外提供类似于 Web-service 的API接口。用户可以通过 http 请求,想搜索引擎服务器提交一定格式的文件,生成索引;也可以通过提出查找请求,并得到返回结果。

Lucene简介

  • Lucene是 Apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。
  • Lucene的目的是:为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为胡超高压华北库去完整的全文检索引擎。Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜索。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库。人们经常提到信息检索程序库,虽然与搜索引擎有关,但不应该将信息检索程序库与搜索引擎相混淆。
  • Luncene是一个全文检索引擎的架构。那什么是全文搜索引擎?
    • 全文搜索引擎是名副其实的搜索引擎,国外具有代表性的有 Google、Fas/AllTheWeb、AltaVista、Inktomi、Teoma、WiseNut等,国内著名的有 百度(Baidu)。它们都是通过从互联网上提取的各个网站的信息(以网页文字为主)而建立的数据库中,检索与用户查询条件匹配的相关记录,然后按一定的排列顺序将结果返回给用户,因此它们是真正的搜索引擎。
    • 从搜索结果来源的角度,全文搜索引擎又可细分为两种,一种是拥有自己的检索程序(Indexer),俗称“蜘蛛”(Spider)程序或“机器人”(Robot)程序,并自建网页数据库,搜索结果直接从自身的数据库中调用,如上面提到的7加引擎;另一种则是租用其他引擎的数据库,并按自定的格式排列搜索结果,如Lycos引擎。

ElasticSearch 和 Solr 比较

对单纯的对已有数据进行搜索时,Solr更快。

ElasticSearch笔记_第2张图片

对实时建立索引时,Solr会产生io阻塞,查询性能较差,ElasticSearch具有明显的优势。

ElasticSearch笔记_第3张图片

随着数据联合的增加,Solr的搜索效率会变得更低,而ElasticSearch 却没有明显的变化。

ElasticSearch笔记_第4张图片

转变我们的搜索基础设施后从Solr ElasticSearch,我们看见一个即时~ 50 x 提高搜索性能!

ElasticSearch笔记_第5张图片

总结:

1、es基本是开箱即用,非常简单,Solr安装略微复杂一点!

2、Solr利用 Zookeeper 进行分布式管理;而 ElasticSearch 自身带有分布式协调管理功能。

3、Solr支持更多格式的数据,比如 Json、XML、CSV、而ElasticSearch 仅支持json文件格式。

4、Solr官方提供的功能更多,而 ElasticSearch 本身更注重于核心功能,高级功能多有第三方插件提供,例如图形化界面需要 kibana 友好支撑。

5、Solr 查询快,但更新索引时慢(即插入删除慢),用于电商等查询多的应用;

  • ES建立索引更快(即查询慢),即实时性查询快,用于facebook、新浪等搜索。
  • Solr是传统搜索应用的有力解决方案,但 ElasticSearch 更实用与新兴的实时搜索应用。

6、Solr比较成熟,有一个更大,更成熟的用户、开发和贡献者社区,而 ElasticSearch 相对开发维护者较少,更新太快,学习使用成本较高。

ElasticSearch安装

声明:JDK1.8,最低要求!ElasticSearch哭护短,界面工具!

Java开发,ElasticSearch 的版本和之后对应的java核心jar包!版本对应!

下载

官网:https://www.elastic.co/cn/

ElasticSearch笔记_第6张图片

ElasticSearch笔记_第7张图片

下载地址:https://www.elastic.co/cn/downloads/elasticsearch

ElasticSearch笔记_第8张图片

ELK 三剑客,解压即用!(web项目!)

Windows下安装!

1、解压就可以使用了!

ElasticSearch笔记_第9张图片

2、目录

bin    启动文件
config   配置文件
	log4j2  日志配置文件
	jvm.options  JVM 虚拟机相关配置
	elasticsearch.yml    elasticsearch 的配置文件! 默认 9200端口!	跨域!
	
lib       相关jar包
logs      日志!
modules   功能模块
plgins    插件! ik

3、启动

ElasticSearch笔记_第10张图片

4、访问测试!

ElasticSearch笔记_第11张图片

安装可视化界面

es head的插件

【注意:需要前端环境】

1、下载地址:https://github.com/mobz/elasticsearch-head

2、启动

npm install
npm run start

3、连接测试发现,存在跨域问题:配置es

http.cors.enabled: true
http.cors.allow-origin: "*"

4、重启es服务器,再次连接

ElasticSearch笔记_第12张图片

这个 head 就当做数据展示工具!查询最好在 Kibana 操作

安装Kibana

了解 ELK

  • ELK 是Elasticsearch、Logstash、Kibana三大开源框架手写字母大写简称。市面上也被称为 Elastic Stack。其中 Elasticsearch是一个基于Lucene、分布式,通过Restful方式进行交互的近实时搜索平台框架。像类似百度、谷歌这种大数据全文搜索引擎的场景都可以使用 Elasticsearch作为底层支持框架,可见ElasticSearch提供的搜索能力确实强大,市面上很多时候我们简称 ElasticSearcj为es。

  • Logstash 是ELK的中央数据流引擎,用于从不同目标(文件/数据存储/MQ)收集的不同格式数据,经过过滤后支持输出到不同目的地(文件/MQ/redis/elasticsearch/kafka等)。Kibana可以将elasticsearch的数据通过友好的页面展示出来,提供实时分析的功能。

  • 市面上很多开发只要提到ELK能够一致说出它是一个日志分析架构技术栈总裁,但实际上ELK不仅仅使用与日志分析,它还可以支持其他任何数据分析和收集的场景,日志分析和收集只是更具有代表性。并非唯一性。

ElasticSearch笔记_第13张图片

安装Kibana

Kibana 是一个针对 ElasticSearch 的开源分析及可视化平爱,用来搜索、查看交互存储在 ElasticSearch索引中的数据。使用Kibana,可以通过各种图标进行高级数据分析及展示。Kibana让海量数据更容易理解。它操作简单,基于浏览器的用户界面可以快速创建仪表盘(dashboard)实时显示 ElasticSearch查询动态。设置 Kibana非常简单。无需编码或者额外的基础架构。几分钟内就可以完成Kibana安装并启动ElasticSearch索引检测。

官网:https://www.elastic.co/cn/elastic-stack

Kibana版本需要和ElasticSearch版本一致!

ElasticSearch笔记_第14张图片

下载地址:https://www.elastic.co/cn/downloads/kibana

ElasticSearch笔记_第15张图片

下载之后,拆箱即用!是一个标准的工程!

好处:ELK基本上都是拆箱即用!

启动测试

1、解压后的目录

ElasticSearch笔记_第16张图片

2、启动

ElasticSearch笔记_第17张图片

3、访问测试

ElasticSearch笔记_第18张图片

4、开发工具!(Post、curl、head、谷歌浏览器插件测试)

ElasticSearch笔记_第19张图片

ElasticSearch笔记_第20张图片

所以操作都在这里进行编写。

5、汉化!修改kibana配置即可!115行! zh-CN!

ElasticSearch笔记_第21张图片

ES核心概念

1、索引

2、字段类型(mapping)

3、文档

4、分片(documents)(倒排索引)

概述

集群,节点,索引,类型,文档,分片,映射是什么?

ElasticSearch 是面向文档,关系型数据库 和 ElasticSearch 客观的对比! 一切都是JSON !

Relational DB ElasticSearch
数据库(database) 索引(indices)
表(tables) types
行(rows) documents
字段(columns) fields

ElasticSearch(集群)中可以包含多个索引(数据库),每个索引中可以包含多个类型(表),每个类型下又包含多个文档(行),每个文档中又包含多个字段(列)。

物理设计:

elasticsearch 在后台把每个 索引划分成多个分片,每片分片 可以在集群中的不同服务器间迁移。

一个 就是一个集群!默认的集群名称就是 elasticsearch

ElasticSearch笔记_第22张图片

逻辑设计:

一个索引类型中,包含多个文档,比如说文档1,文档2。当我们索引一篇文档时,可以通过这样的一各顺序找到它:索引 -> 类型 -> 文档ID,通过这个组合我们就能索引到某个具体的文档。注意:ID不必是整数,实际上它是个字符串。

文档

就是一条一条的数据

user
1   zhangsan  18
2   kingtl    20
  • elasticsearch是面向文档的,那么就意味着索引和搜索数据的最小单位是文档,elasticsearch中,文档有几个 重要属性:
    • 自我包含,一篇文档同时包含字段和对应的值,也就是同时包含 key:value!
    • 可以是层次型的,一个文档中包含子文档,复杂的逻辑实体就是这么来的!
    • 灵活的结构,文档不依赖预先定义的模式,关系型数据库中,要提前定义字段才能使用,在elasticsearch中,对于字段是非常灵活的,有时候,我们可以忽略该字段,或者动态的添加一个新的字段。
  • 尽管可以随意的新增或者忽略某个字段,但是,每个字段的类型非常重要,比如一个年龄字段类型,可以是字符串也可以是整形。因为elasticsearch会保存字段和类型之间的映射即其他的设置。这种映射具体到每个映射的每种类型,这也是为什么在elasticsearch中,类型有时候也成为映射类型。

类型

  • 类型是文档的逻辑容器,就像关系型数据库一样,表格是行的容器。类型中对于字段的定义称为映射,比如 name 映射为字符串类型。文档时无模式的,不需要拥有映射中所定义的所有字段,比如新增一个字段,那么elasticsearch是怎么做的呢?
  • ElasticSear会自动的将新字段加入映射,但是这个字段的不确定它是什么类型,elasticsearch就开始才,如果这个值时18,那么ElasticSearch会认为它是整形,但是elasticsearch也可能猜不对,所以最安全的方式就是提前定义好所需要的的映射,这点跟关系型数据库殊途同归了,先定义好字段,然后再使用。

索引

就是数据库!

  • 索引是映射;类型的容器,elasticsearch中的索引是一个非常大的文档集合。索引存储了映射类型的字段和其他配置。然后它们被存储到了各个分片上了。

物理设计:节点和分片 如何工作

ElasticSearch笔记_第23张图片

一个集群至少有一个节点,而一个节点就是一个elasticsearch进程,节点可以有很多歌默认的,如果你创建索引,那么索引将会有5个分片(primary shard,又称主分片)否成的,每一个主分片会有一个副本(replica shard,又称复制分片)

ElasticSearch笔记_第24张图片

上图是一个有3个节点的集群,可以看到主分片和对应的复制分片都不会再同一个节点内,这样有利于某个接地那挂掉了,数据也不至于丢书。实际上,一个分片是一个Lucene索引,一个包含倒排索引的文件目录,倒排索引的结构使得 elasticsearch 在不扫描全部文档的情况下,就能告诉你哪些文档包含特定的关键字。

倒排索引

  • elasticsearch使用的是一种成为 倒排索引的结构,采用Lucene倒排索作为底层。这种结构适用于快速的全文搜索,一个索引由文档中所有不重复的列表构成,对于每一个词,都有一个包含它的文档列表。例如,现在有两个文档,每个文档包含如下内容:
Study every day, good good up to forever  # 文档1 包含的内容
To forever,study every day, good good up   # 文档2 包含的内容
  • 为了创建倒排索引,我们首先要将每个文档拆分成独立的词(或成为词条或者tokens),然后创建一个包含所有不重复的词条的排序列表,然后列出每个词条出现在哪个文档:
term doc_1 doc_2
Study ×
To ×
every
forever
day
study ×
good
to ×
up

现在,视图搜索 to forever,只需要查看包含每个词条的文档 score

term doc_1 doc_2
to ×
forever
total 2 1

两个文档都匹配,但是第一个文档比第二个匹配程度更高。如果没有别的条件,现在,者两个包含关键字的文档都将返回。

再看一个示例。比如通过博客标签来搜索博客文章,那么倒排索引列表就是这样一个结构

ElasticSearch笔记_第25张图片

  • 如果要搜索含有 python 标签的文章,那相对于查找所有原始数据而言,查找倒排索引后的数据将会快的多。只需要 查看标签这一栏,然后获取相关的文章ID即可。
  • ElasticSearch的索引和Lucene的索引对比。
  • 在ElasticSearch中,索引(库)这个词被频繁使用,这就是属于的使用。在elasticsearch中,索引被分为多个分片,没份 分片是一个 Lucene的索引。所以一个elasticsearch索引是由多个Lucene索引组成的。因为Lucene是elasticsearch的底层。如果没有特指,说起索引都是指 elasticsearch的索引!

IK分词器插件

什么是IK分词器?

  • 分词:即把一段中文或者别的划分成为一个个的换剪子,我们在搜索时候会把自己的信息进行粉刺,会把数据库中或者索引库中的数据进行分词,然后进行一个匹配操作,默认的中文分词是将每个字看成一个词。比如:“分词器”会被分成 “分”,“词”,“器”,这是不符合要求的,所以需要安装中文分词器IK来解决这个问题。
  • 如果使用中文,建议使用IK分词器
  • IK提供了两个分词算法:ik_smart 和 ik_max_word,其中 ik_smart 为最少切分,ik_max_word为最细粒度划分!

安装

1、网址:https://github.com/medcl/elasticsearch-analysis-ik

2、下载完毕之后,放入elasticsearch插件中即可!

3、重启观察ElasticSearch

ElasticSearch笔记_第26张图片

4、elasticsearch-plugin 可以通过这个命令来查看加载进来的插件

ElasticSearch笔记_第27张图片

5、使用Kibana 进行测试!

查看不同的分词器效果

ik_smart 为最少切分

ElasticSearch笔记_第28张图片

ik_max_word为最细粒度划分!穷尽词库的可能!字典!

ElasticSearch笔记_第29张图片

输入 分布式全文检索引擎

ElasticSearch笔记_第30张图片

自己需要的词,可以自己加入到分词器的字典当中去!

IK分词器增加自己的配置!

ElasticSearch笔记_第31张图片

重启ES,看细节

ElasticSearch笔记_第32张图片

测试

ElasticSearch笔记_第33张图片

Rest风格说明

一种软件架构风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁、更有层次,更易于实现缓存等机制。

基本的Rest命令说明:

method url地址 描述
PUT localhost:9200/索引名称/类型名称/文档id 创建文档(指定文档id)
POST localhost:9200/索引名称/类型名称 创建文档(随机文档id)
POST localhost:9200/索引名称/类型名称/文档id/_update 修改文档
DELETE localhost:9200/索引名称/类型名称/文档id 删除文档
GET localhost:9200/索引名称/类型名称/文档id 查询文档通过文档id
POST localhost:9200/索引名称/类型名称/_search 查询所有数据

关于索引的基本操作

基础测试

1、创建一个索引

PUT /索引名/~类型名~/文档id
{
	请求体
}

ElasticSearch笔记_第34张图片

完成了自动增加了增加索引!数据也成功的添加!

ElasticSearch笔记_第35张图片

3、类型

  • 字符串类型

text、keyword

  • 数值类型

long、integer、short、byte、double、float、half float、scaled float

  • 日期类型

date

  • te布尔值类型

boolean

  • 二进制类型

binary

  • 等等....

4、指定字段的类型

创建规则:

ElasticSearch笔记_第36张图片

获得规则

可以通过 GET请求获取具体的信息

ElasticSearch笔记_第37张图片

5、查看默认的信息

ElasticSearch笔记_第38张图片

ElasticSearch笔记_第39张图片

如果文档字段没有指定,那么 es 就会默认配置 字段类型!

扩展:通过命令 elasticsearch 索引情况!通过get _cat/ 可以获得es当前的很多信息!

修改索引 提交还是使用PUT 即可! 然后覆盖值!

旧的方法:

ElasticSearch笔记_第40张图片

现在的方法:

ElasticSearch笔记_第41张图片

删除索引!

通过DELETE 命令删除,根据请求判断删除索引还是删除文档记录

使用Restful 风格是ES推荐使用的!

ElasticSearch笔记_第42张图片

关于文档的基本操作(重点)

基本操作

1、添加数据

PUT /kingtl/user/1
{
  "name": "kingtl",
  "age": 23,
  "desc": "elasticsearch学习",
  "tags": ["技术宅","游戏"]
}

ElasticSearch笔记_第43张图片

2、获取数据

ElasticSearch笔记_第44张图片

3、更新数据 PUT

ElasticSearch笔记_第45张图片

4、POST _update 【推荐使用的更新方式】

ElasticSearch笔记_第46张图片

简单的搜索

GET kingtl/user/1

简单的条件查询,可以根据默认的映射规则,产生基本的查询!

ElasticSearch笔记_第47张图片

复杂操作 搜索

ElasticSearch笔记_第48张图片

参数解释

hit:
	索引和文档的信息
	查询的结果总数
	然后就是查询出来的具体的文档
	数据中的东西都可以遍历出来了
	分数:我们可以通过来判断谁更加符合结果

ElasticSearch笔记_第49张图片

结果过滤

ElasticSearch笔记_第50张图片

Java操作ElasticSearch,所有的方法和对象就是这里面的key!

排序!

ElasticSearch笔记_第51张图片

分页查询 !

size:单页面返回多少条的数据

ElasticSearch笔记_第52张图片

数据下标还是从0开始的,和学的所有数据结构是一样的!

布尔值查询

must (and),所有的条件都要符合 where id =1 and name = xxx

多条件查询

ElasticSearch笔记_第53张图片

should(or),所有的条件满足一种即可 where id =1 or name =xxx

ElasticSearch笔记_第54张图片

must not (not)

ElasticSearch笔记_第55张图片

过滤器 filter

ElasticSearch笔记_第56张图片

  • gt 大于
  • gte 大于等于
  • lt 小于
  • lte 小于等于

ElasticSearch笔记_第57张图片

匹配多个条件

tags: 满足其中一个,就可以被查出,这个时候可以通过分值来进行判断

ElasticSearch笔记_第58张图片

精确查询!

term 查询是直接通过倒排索引指定的词条进行精确的查找

关于分词:

  • term,直接查找精确的值
  • match,会使用分词器解析!(先分析文档,然后再通过分析的文档进行查询!)

两个类型 text keyword

ElasticSearch笔记_第59张图片

keyword 字段类型不会被分词器解析

ElasticSearch笔记_第60张图片

ElasticSearch笔记_第61张图片

多个值匹配精确查询

ElasticSearch笔记_第62张图片

高亮查询!

ElasticSearch笔记_第63张图片

ElasticSearch笔记_第64张图片

  • 匹配
  • 按照条件匹配
  • 精确匹配
  • 区间范围匹配
  • 匹配字段过滤
  • 多条件查询
  • 高亮查询

集成SpringBoot

找官方文档

网址 https://www.elastic.co/guide/index.html

ElasticSearch笔记_第65张图片

ElasticSearch笔记_第66张图片

ElasticSearch笔记_第67张图片

ElasticSearch笔记_第68张图片

1、找到原生依赖


    org.elasticsearch.client
    elasticsearch-rest-high-level-client
    7.8.1

2、对象

ElasticSearch笔记_第69张图片

3、分析这个类中的方法即可!

配置基本的项目!

一定要保证 导入的依赖和 es 版本一致!

ElasticSearch笔记_第70张图片

ElasticSearch笔记_第71张图片

源码中提供的对象

虽然导入了3个类,静态内部类,核心类就只有一个 源码类:

/*
 * Copyright 2012-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.autoconfigure.elasticsearch;

import java.net.URI;
import java.net.URISyntaxException;
import java.time.Duration;

import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

/**
 * Elasticsearch rest client infrastructure configurations.
 *
 * @author Brian Clozel
 * @author Stephane Nicoll
 * @author Vedran Pavic
 * @author Evgeniy Cheban
 */
class ElasticsearchRestClientConfigurations {

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnMissingBean(RestClientBuilder.class)
	static class RestClientBuilderConfiguration {

		@Bean
		RestClientBuilderCustomizer defaultRestClientBuilderCustomizer(ElasticsearchRestClientProperties properties) {
			return new DefaultRestClientBuilderCustomizer(properties);
		}

        //RestClientBuilder
		@Bean
		RestClientBuilder elasticsearchRestClientBuilder(ElasticsearchRestClientProperties properties,
				ObjectProvider builderCustomizers) {
			HttpHost[] hosts = properties.getUris().stream().map(this::createHttpHost).toArray(HttpHost[]::new);
			RestClientBuilder builder = RestClient.builder(hosts);
			builder.setHttpClientConfigCallback((httpClientBuilder) -> {
				builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(httpClientBuilder));
				return httpClientBuilder;
			});
			builder.setRequestConfigCallback((requestConfigBuilder) -> {
				builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(requestConfigBuilder));
				return requestConfigBuilder;
			});
			builderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
			return builder;
		}

		private HttpHost createHttpHost(String uri) {
			try {
				return createHttpHost(URI.create(uri));
			}
			catch (IllegalArgumentException ex) {
				return HttpHost.create(uri);
			}
		}

		private HttpHost createHttpHost(URI uri) {
			if (!StringUtils.hasLength(uri.getUserInfo())) {
				return HttpHost.create(uri.toString());
			}
			try {
				return HttpHost.create(new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), uri.getPath(),
						uri.getQuery(), uri.getFragment()).toString());
			}
			catch (URISyntaxException ex) {
				throw new IllegalStateException(ex);
			}
		}

	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(RestHighLevelClient.class)
	static class RestHighLevelClientConfiguration {

        //RestHighLevelClient 高级客户端
		@Bean
		@ConditionalOnMissingBean
		RestHighLevelClient elasticsearchRestHighLevelClient(RestClientBuilder restClientBuilder) {
			return new RestHighLevelClient(restClientBuilder);
		}

		@Bean
		@ConditionalOnMissingBean
		RestClient elasticsearchRestClient(RestClientBuilder builder,
				ObjectProvider restHighLevelClient) {
			RestHighLevelClient client = restHighLevelClient.getIfUnique();
			if (client != null) {
				return client.getLowLevelClient();
			}
			return builder.build();
		}

	}

	@Configuration(proxyBeanMethods = false)
	static class RestClientFallbackConfiguration {

        //RestClient  普通的客户端
		@Bean
		@ConditionalOnMissingBean
		RestClient elasticsearchRestClient(RestClientBuilder builder) {
			return builder.build();
		}

	}

	static class DefaultRestClientBuilderCustomizer implements RestClientBuilderCustomizer {

		private static final PropertyMapper map = PropertyMapper.get();

		private final ElasticsearchRestClientProperties properties;

		DefaultRestClientBuilderCustomizer(ElasticsearchRestClientProperties properties) {
			this.properties = properties;
		}

		@Override
		public void customize(RestClientBuilder builder) {
		}

		@Override
		public void customize(HttpAsyncClientBuilder builder) {
			builder.setDefaultCredentialsProvider(new PropertiesCredentialsProvider(this.properties));
		}

		@Override
		public void customize(RequestConfig.Builder builder) {
			map.from(this.properties::getConnectionTimeout).whenNonNull().asInt(Duration::toMillis)
					.to(builder::setConnectTimeout);
			map.from(this.properties::getReadTimeout).whenNonNull().asInt(Duration::toMillis)
					.to(builder::setSocketTimeout);
		}

	}

	private static class PropertiesCredentialsProvider extends BasicCredentialsProvider {

		PropertiesCredentialsProvider(ElasticsearchRestClientProperties properties) {
			if (StringUtils.hasText(properties.getUsername())) {
				Credentials credentials = new UsernamePasswordCredentials(properties.getUsername(),
						properties.getPassword());
				setCredentials(AuthScope.ANY, credentials);
			}
			properties.getUris().stream().map(this::toUri).filter(this::hasUserInfo)
					.forEach(this::addUserInfoCredentials);
		}

		private URI toUri(String uri) {
			try {
				return URI.create(uri);
			}
			catch (IllegalArgumentException ex) {
				return null;
			}
		}

		private boolean hasUserInfo(URI uri) {
			return uri != null && StringUtils.hasLength(uri.getUserInfo());
		}

		private void addUserInfoCredentials(URI uri) {
			AuthScope authScope = new AuthScope(uri.getHost(), uri.getPort());
			Credentials credentials = createUserInfoCredentials(uri.getUserInfo());
			setCredentials(authScope, credentials);
		}

		private Credentials createUserInfoCredentials(String userInfo) {
			int delimiter = userInfo.indexOf(":");
			if (delimiter == -1) {
				return new UsernamePasswordCredentials(userInfo, null);
			}
			String username = userInfo.substring(0, delimiter);
			String password = userInfo.substring(delimiter + 1);
			return new UsernamePasswordCredentials(username, password);
		}

	}

}

具体的API测试!

1、创建索引

2、判断索引是否存在

3、删除索引

4、创建文档

5、CRUD文档!

package com.king;

import com.alibaba.fastjson.JSON;
import com.king.pojo.User;
import com.king.utils.ESconst;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

/**
 * ES 7.8.1 高级客户端 测试API
 */
@SpringBootTest
class KingEsApiApplicationTests {

	@Autowired
	@Qualifier("restHighLevelClient")
	private RestHighLevelClient client;

	// 面向对象来操作
	// 测试索引的创建   Request
	@Test
	void testCreateIndex() throws IOException {
		// 1、创建索引请求
		CreateIndexRequest request = new CreateIndexRequest("king_index");
		//2、执行创建请求
		CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);

		System.out.println(createIndexResponse);
	}

	// 测试获取索引 判断其是否存在
	@Test
	void testExistsIndex() throws IOException {
		GetIndexRequest request = new GetIndexRequest("king_index");
		boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
		System.out.println(exists);
	}
	// 测试删除索引
	@Test
	void testDeleteIndex() throws IOException {
		DeleteIndexRequest request = new DeleteIndexRequest("king_index");
		//删除
		AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
		System.out.println(delete.isAcknowledged());
	}

	// 测试添加文档
	@Test
	void testAddDocument() throws IOException {
		//1、创建对象
		User user = new User("法外狂徒张三", 3);
		//2、创建请求
		IndexRequest request = new IndexRequest("king_index");
		//3、 规则   put /king_index/_doc/1
		request.id("1");
		request.timeout(TimeValue.timeValueSeconds(1));
		request.timeout("1s");

		//4、数据放入请求   json
		request.source(JSON.toJSONString(user), XContentType.JSON);

		// 5、客户端发送请求,获取响应的结果
		IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);

		System.out.println(indexResponse.toString()); //
		System.out.println(indexResponse.status());   //对应命令返回的状态  CREATED

	}

	// 获取文档,判断是否存在  get   /king_index/_doc/1
	@Test
	void testIsExists() throws IOException {
		GetRequest getRequest = new GetRequest("king_index","1");
		// 不获取返回的 _source 的上下文
		getRequest.fetchSourceContext(new FetchSourceContext(false));
		getRequest.storedFields("_none");

		boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);
		System.out.println(exists);

	}

	// 获取文档信息
	@Test
	void testGetDocument() throws IOException {
		GetRequest getRequest = new GetRequest("king_index","1");
		GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
		System.out.println(getResponse.getSourceAsString()); //打印文档的内容
		System.out.println(getResponse);  //返回的全部内容,和命令是一样的

	}

	// 更新文档信息
	@Test
	void testUpdateDocument() throws IOException {
		UpdateRequest updateRequest = new UpdateRequest("king_index", "1");
		updateRequest.timeout("1s");

		User user = new User("zhangsan1", 18);
		updateRequest.doc(JSON.toJSONString(user),XContentType.JSON);

		UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);
		System.out.println(updateResponse.status());
	}

	// 删除文档记录
	@Test
	void testDeleteDocument() throws IOException {
		DeleteRequest request = new DeleteRequest("king_index","1");
		request.timeout("1s");

		DeleteResponse deleteResponse = client.delete(request, RequestOptions.DEFAULT);
		System.out.println(deleteResponse.status());
	}


	// 真实项目中 一般都会批量插入数据!
	@Test
	void testBulkRequest() throws IOException {
		BulkRequest bulkRequest = new BulkRequest();
		bulkRequest.timeout("10s");

		ArrayList userList = new ArrayList<>();
		userList.add(new User("张三1",3));
		userList.add(new User("张三2",3));
		userList.add(new User("张三3",3));
		userList.add(new User("李四1",3));
		userList.add(new User("李四2",3));
		userList.add(new User("李四3",3));

		// 批处理请求
		for (int i = 0; i < userList.size(); i++) {

			//批量更新、删除,修改这里对应的请求即可!
			bulkRequest.add(
					new IndexRequest("king_index")
					.id(""+(i+1))
					.source(JSON.toJSONString(userList.get(i)),XContentType.JSON));
		}

		BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
		System.out.println(bulkResponse.hasFailures());    // 是否失败,返回 false 代表成功!
	}


	// 查询
	//SearchRequest   请求构造
	//SearchSourceBuilder   条件构造
	//HighlightBuilder   构建高亮
	// TermQueryBuilder   精确查询
	//MatchAllQueryBuilder  匹配全部
	// xxx QueryBuilder    对应ES全部API
	@Test
	void testSearch() throws IOException {
		SearchRequest searchRequest = new SearchRequest(ESconst.ES_INDEX);
		//构建搜索的条件
		SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
		// 查询条件, 可以使用QueryBuilders 工具类来实现
		// termQuery   精确匹配
		//  matchAllQuery 匹配所有
		//MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
		TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "zhangsan1");
		sourceBuilder.query(termQueryBuilder);

		sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

		SearchRequest source = searchRequest.source(sourceBuilder);
		SearchResponse searchResponse = client.search(source, RequestOptions.DEFAULT);
		System.out.println(JSON.toJSONString(searchResponse.getHits()));
		System.out.println("================================================");
		for (SearchHit documentFields : searchResponse.getHits().getHits()) {
			System.out.println(documentFields.getSourceAsMap());
		}
	}



}

你可能感兴趣的:(ElasticSearch笔记)