ElasticSearch狂神说笔记

ElasticSearch狂神说笔记

来源:https://www.bilibili.com/video/BV17a4y1x7zq

狂神聊ElasticSearch

版本:ElasticSearch 7.6.1(全网最新了)!

  1. X 7.X的区别十分大,6.X的API(原生API,RestFul高级!)

我们要讲解什么?

SQL:like%狂神说%,如果是大数据,就十分慢!索引!

ElasticSearch:搜索!(百度、github、淘宝电商!)

内容:

  1. 聊一个人

  2. 货比三家

  3. 安装

  4. 生态圈

  5. 分词器ik

  6. RestFul操作 ES

  7. CRUD

  8. SpringBoot集成ElasticSearch(从原理分析!)

  9. 爬虫爬取数据

  10. 实战,模拟全文检索!

    以后如果需要用到搜索,就可以使用ES!(大数据量的情况下使用!)


聊聊Doug Cutting

本故事内容来自公众号:鲜枣课堂

1998年9月4日,Google公司在美国的硅谷成功。正如大家所知,它是一家做搜索引擎起来的公司。

ElasticSearch狂神说笔记_第1张图片

无所有偶,一位名叫Doug Cutting的美国工程师,也迷上了搜索引擎,他做了一个用于文本搜索的函数库(姑且理解为软件的功能组件),命名为Lucene。

ElasticSearch狂神说笔记_第2张图片

Lucene使用Java写成的,目标是为各种中小型应用软件加入全文检索功能,因为好用而且开源(代码公开),非常受程序员们的欢迎。

早期的时候,这个项目被发布在Doug Cutting的个人网站和SourceForge(一个开源软件网站),后来,2001年底,Lucene成为Apache软件基金会jakarta项目的子项目。

ElasticSearch狂神说笔记_第3张图片

2004年,Doug Cutting再接再厉,在Lucene的基础上,和Apache开源伙伴Mike Cafarella合作,开发了一款可以替代当时的主流搜索的开源搜索引擎,命名为Nutch.

ElasticSearch狂神说笔记_第4张图片

Nutch是一个建立在Lucene核心之上的网页搜索引用程序,可以下载下来直接使用,它在Lucene的基础上加了网络爬虫和一些网页相关的功能,目的就是从一个简单的站内搜索推广到全球网络的搜索上,就像Google一样。

Nutch在业界的影响力比Lucene更大。

大批网站采用了Nutch平台,大大降低了技术门槛,使低成本的普通计算机取代高价的Web服务器成为可能。甚至有一段时间。在硅谷有了一股用Nutch低成本创业的潮流(大数据!)


随着时间的推移,无论是Google还是Nutch,都面临搜索对象“体积”不断增大的问题。

尤其是Google,作为互联网搜索引擎,需要存储大量的网页,并不断优化自己的搜索算法,提升搜索效率。

ElasticSearch狂神说笔记_第5张图片

在这个过程中,Google确实找到了不少好办法,并且无私地分享了出来。

2003年,Google发表了一篇技术学术论文,公开介绍了自己的谷歌文件系统GDS(Google File System)。这是Google公司为了存储海量搜索数据而设计的专用文件系统。

第二年,也就是2004年,Doug Cutting基于Google的GFS论文,实现了分布式文件存储系统,并将它命令为NDFS(Nutch Distributed File System)。

ElasticSearch狂神说笔记_第6张图片

还是2004年,Google又发表了一篇技术学术论文,介绍自己的MapReduce编程模型,这个编程模型用于大规模数据集(大于1TB)的并行分析运算。

第二年(2005年),Doug Cutting又基于MapReduce,在Nutch搜索引擎实现了该功能。

ElasticSearch狂神说笔记_第7张图片

2006年,当时依然很厉害的Yahoo(雅虎)公司,招安了Doug Cutting。

ElasticSearch狂神说笔记_第8张图片

加盟Yahoo之后,Doug Cutting将NDFS和MapReduce进行了升级改造,并重新命名为Hadoop(NDFS也改名为HDFS,Hadoop Distributed File System)。

这个就是后来大名鼎鼎的大数据框架系统——Hadoop的由来,而Doug Cutting,则被人们称为Hadoop之父。

ElasticSearch狂神说笔记_第9张图片

Hadoop这个名字,实际上是Doug Cutting他儿子的黄色玩具大象的名字,所以,Hadoop的Logo,就是一只奔跑的黄色大象。

ElasticSearch狂神说笔记_第10张图片

我们继续往下说。

还是2006年,Google又发论文了。

这次,他们介绍了自己的BigTable,这是一种分布式数据存储系统,一种用来处理海量数据的非关系型数据库。

Doug Cutting当然也没有放过,在自己的Hadoop系统里面,引入了BigTable,并命名为HBase。

ElasticSearch狂神说笔记_第11张图片

好吧,反正就是紧跟Google时代步伐,你出什么,我学什么。

所以,Hadoop的核心部分,基本上都有Google的影子。

ElasticSearch狂神说笔记_第12张图片

2008年1月,Hadoop成功上位,正是成为Apache基金会的顶级项目。

同年2月,Yahoo宣布建成了一个拥有1万个内核的Hadoop集群,并将自己的搜索引擎产品部署在上面。

7月,Hadoop打破世界纪录,成为最快排序1TB数据的系统,用时209秒。




回到主题

Lucene是一套信息检索工具包!jar包!不包含搜索引擎系统!

包含的:索引结构!读写索引的工具!排序,搜索规则…工具类!

Lucene和ElasticSearch关系:

ElasticSearch是基于Lucene做了一些封装和增强(我们上手十分简单!)


ElasticSearch概述

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

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

历史

多年前,一个叫做 Shay Banon 的刚结婚不久的失业开发者,由于妻子要去伦敦学习厨师,他便跟着也去了。在他找工作的过程中,为了给妻子构建一个食谱的搜索引擎,他开始构建一个早期版本的Lucene。

直接基于Lucene工作会比较困难,所以 Shay 开始抽象 Lucene 代码以便 java 程序员可以在应用中添加搜索功能。他发布了他的第一个开源项目,叫做 Compass"。

后来 Shy 找到一份工作,这份工作处在高性能和内存数据网格的分布式环境中,因此高性能的、实时的、分布式的搜索引擎也是理所当然需要的,然后他决定重写 Compass 库使其成为一个独立的服务叫做 Elasticsearch。

第一个公开版本出现在 2010 年 2 月,在那之后 Elasticsearch 已经成为 Github 上最受欢迎的项目之一,代码贡献者超过300人。一家主营 Elasticsearch 的公司就此成立,他们一边提供商业支持一边开发新功能,不过 Elasticsearch 将永远开源目对所有人可用。

谁在使用:

  1. 维基百科,类似百度百科,全文检索,高亮,搜索推荐(权重);
  2. The Guardian (国外新闻网站),类似搜孤新闻,用户行为日志(点击,浏览,收藏,评论)+ 社交网络数据(对某某新闻的相关看法),数据分析,给到每篇新闻文章的作者,让他知道他的文章的公众反馈(好,坏,热门,垃圾,鄙视,崇拜);
  3. Stack Overflow (国外的程序异常讨论论坛),it 问题,程序的报错,提交上去,有人会跟你讨论和回答,全文检索,搜索相关问题和答案,程序报错了,就会将报错信息粘贴到里面去,搜索有没有对应的答案
  4. GitHub (开源代码管理),搜索上千亿行代码;
  5. 电商网站检索商品;
  6. 日志数据分析,logstash 采集日志,ES 进行复杂的数据分析,ELK 技术,elasticsearch + logstash + kibana;
  7. 商品价格监控网站,用户设定某商品的价格阈值,当低于该阈值的时候,发送通知消息给用户,比如说订阅牙膏的监控,如果高露洁牙膏的家庭套装低于 50 块钱,就通知我,我就去买;
  8. BI 系统,商业智能,Business Intelligence,比如说有个大型商场集团,分析一下某某区域最近 3 年的用户消费金额的趋势以及用户群体的组成构成,产出相关的数张报表;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 ™ 的开源搜索引擎,无论在开源还是专有领域,Lucene 可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库,但是,Lucene 只是一个库,想要使用它,你必须使用 java 来作为开发语言并将其直接集成到你的应用中,更糟糕的是 Lucene 非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的,Elasticsearch 也使用 java 开发并使用 Lucene 作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的Restful API (比如:http://localhost:81/app/zhangsan)来隐藏 Lucene 的复杂性,从而让全文搜索变得简单。


Solr简介

​ Solr是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器。Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进行了优化

​ Solr可以独立运行,运行在Jetty、Tomcat等这些Servlet容器中,Solr索引的实现方法很简单,用POST方法向Solr服务器发送一个描述Field 及其内容的XML文档,Solr根据xml文档添加、删除、更新索引。Solr搜索只需要发送HTTPGET请求,然后对Solr返回Xml.json等格式的查询结果进行解析,组织页面布局。Solr不提供构建UI的功能,Solr提供了一个管理界面,通过管理界面可以查询Solr的配置和运行情况。
​ solr是基于lucene开发企业级搜索服务器,实际上就是封装了lucene。
​ Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的APl接口(比如:http://localhost:81/app?name=zhangsan)。用户可以通过http请求,向搜索引擎服务器提交一定格式的文件,生成索引;也可以通过提出查找请求,并得到返回结果。


Lucene简介

​ Lucene是apache软件基金会 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库。人们经常提到信息检索程序库,虽然与搜索引擎有关,但不应该将信息检索程序库与搜索引擎相混淆。


ElasticSearch和Solr的比较

img

img

img

img


ES vs Solr 总结
  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包版本对应!JDK环境正常!

下载

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

ElasticSearch狂神说笔记_第13张图片

ElasticSearch狂神说笔记_第14张图片

点击即可下载!(Windows平台)

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


我们这里先在Windows下学习!

ELK三剑客,解压即用!(web项目!前端环境!)

Windows下安装

1、解压

ElasticSearch狂神说笔记_第15张图片

2、 熟悉目录!

bin  启动文件
config  配置文件
	log4j2   日志配置文件
	jvm.options  java虚拟机相关的配置(根据个人电脑内存大小设置,设置的越大,用起来越爽)
	elasticsearch.yml    elasticsearch的配置文件! 默认 9200 端口!跨域!
lib   相关jar包
logs  日志!
modules  功能模块
plugins  插件!

3、启动(以管理员身份运行)

ElasticSearch狂神说笔记_第16张图片

注意:该使用版本是:elasticsearch-8.7.1

elasticsearch.yml中配置

  • 跳过输入密码:

    xpack.security.enabled: false
    
  • 端口:

    http.port: 9200
    
  • 主机ip

    http.host: 127.0.0.1
    
  • 如果有闪退或者需要输入用户名密码验证,可以配置如下解决!

    xpack.security.enabled: false
    
    xpack.security.enrollment.enabled: false
    
    # Enable encryption for HTTP API client connections, such as Kibana, Logstash, and Agents
    xpack.security.http.ssl:
      enabled: false
      keystore.path: certs/http.p12
    
    # Enable encryption and mutual authentication between cluster nodes
    xpack.security.transport.ssl:
      enabled: false
      verification_mode: certificate
      keystore.path: certs/transport.p12
      truststore.path: certs/transport.p12
    # Create a new cluster with the current node only
    # Additional nodes can still join the cluster later
    cluster.initial_master_nodes: ["DESKTOP-5CH94VC"]
    

4、验证是否已经启动成功,访问:http://localhost:9200,如果出现一下页面,说明启动成功!

ElasticSearch狂神说笔记_第17张图片

安装可视化界面es head插件

1、下载地址:https://gitcode.net/mirrors/mobz/elasticsearch-head/

2、启动

npm install
npm run start

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

# 解决跨域问题
http.core.enabled: true
http.core.allow-origin: "*"

4、启动ES服务器,然后再次连接,访问:http://localhost:9100;

ElasticSearch狂神说笔记_第18张图片

初学者,可以把ES中的索引当做MySQL中的库,文档当做库中的数据(一个文档即为一行数据)!

这个head我们就把它当做数据展示工具!我们后面所有的查看,用Kibana


了解ELK

ELK是elastic公司提供的一套完整的日志收集以及展示的解决方案,是Elasticsearch,Logstash 和 Kibana三个产品的首字母缩写,这三款都是开源产品。

ElasticSearch(简称ES),是一个实时的分布式搜索和分析引擎,它可以用于全文搜索,结构化搜索以及分析。

Logstash,是一个数据收集引擎,主要用于进行数据收集、解析,并将数据发送给ES。支持的数据源包括本地文件、ElasticSearch、MySQL、Kafka等等。

Kibana,为 Elasticsearch 提供了分析和 Web 可视化界面,并生成各种维度表格、图形。

ElasticSearch狂神说笔记_第19张图片


安装Kibana

Kibana是一个开源的分析和可视化平台,设计用于和Elasticsearch一起工作。

你用Kibana来搜索,查看,并和存储在Elasticsearch索引中的数据进行交互。

你可以轻松地执行高级数据分析,并且以各种图标、表格和地图的形式可视化数据。

Kibana使得理解大量数据变得很容易。它简单的、基于浏览器的界面使你能够快速创建和共享动态仪表板,实时显示Elasticsearch查询的变化。

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

ElasticSearch狂神说笔记_第20张图片

ElasticSearch狂神说笔记_第21张图片
ES与Kibana的版本要保持一致;

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

启动测试

1、解压后的目录:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-98dnM81Q-1685623999979)(E:\Typora\image\image-20230521120924566.png)]

2、启动进入bin目录,点击Kibana.bat(运行耗时,需要耐心等待)

ElasticSearch狂神说笔记_第22张图片

3、访问测试:http://localhost:5601
ElasticSearch狂神说笔记_第23张图片

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

ElasticSearch狂神说笔记_第24张图片

我们之后的所有操作都在这里进行编写!

5、汉化!自己修改Kibana配置即可!zh-CN!

ElasticSearch狂神说笔记_第25张图片

ElasticSearch狂神说笔记_第26张图片



ES核心概念

概述

在前面的学习中,我们已经掌握的ES是什么,同时也把ES服务已经安装启动,那么ES是如何取存储数据,数据结构是什么,有事如何实现搜索的呢?我们先来聊聊ElasticSearch的相关概念吧!

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

elasticsearch是面向文档,关系行数据库和elasticsearch客观的对比!

Relational DB Elasticsearch
数据库(database) 索引(indices)
表(table) types
行(rows) documents
字段(columns) feilds

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

物理设计:

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

逻辑设计:

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


文档

之前说ElasticSearch是面向文档,那么就意味着索引和搜索数据的最小单位是文档,ElasticSearch中,文档有几个重要属性:

  • 自我包含,一篇文档中同时包含字段和对应的值,也就是同时包含key-value;
  • 可以是层次型的;
  • 灵活的结构,文档不依赖预先定义的模式;

尽管我们可以随意的新增或者忽略某个字段,但是,每个字段的类型非常重要,比如一个年龄字段类型,可以是字符,也可以是整型,因为ES会包含字段和类型之间的映射及其他的设置,这种映射具体到每个映射的每种类型,这也是为什么在ES中,类型有时候也称为映射类型。


类型

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


索引

就是数据库!

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



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

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

ElasticSearch狂神说笔记_第27张图片

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

倒排索引

ES使用的是一种称为倒排索引的结构,采用Lucene倒排索引作为底层。这种结构适用于快速的全文搜索,一个索引由文档中所有不重复的列表构成,对于每一个词,都有一个包含它的文档列表,例如,现在有两个文档,每个文档包含如下内容:

ElasticSearch狂神说笔记_第28张图片

现在我们试图搜索to forever,只要查到包含每个词条的文档

ElasticSearch狂神说笔记_第29张图片

ElasticSearch狂神说笔记_第30张图片

IK分词器插件

什么是IK分词器

分词:即把一段中文或者别的划分成一个个的关键字,我们在搜索时候会把自己的信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行一个匹配操作,默认的中文分词是将每个字看成一个词,比如“我爱狂神”会被分为“我“,”爱“,”狂“”,“神”,这显然是不符合要求的,所以我们需要安装中文分词器ik来解决这个问题。

IK提供了两个分词算法:ik_smart和ik_max_word,其中ik_smart为最少切分,ik_max_word为最细粒度划分!一会我们测试!

安装

1、下载地址:https://github.com/medcl/elasticsearch-analysis-ik

2、下载完毕之后,放入到我们的elasticsearch插件即可!

ElasticSearch狂神说笔记_第31张图片

3、重启观察ES,可以看到IK分词被加载

ElasticSearch狂神说笔记_第32张图片

4、访问http://locahost:5601

  • 最小粒度划分(ik_smart):

    GET _analyze
    {
      "analyzer":"ik_smart",
      "text": ["中国共产党"]
    }
    
  • 最大粒度划分(ik_max_word):

    GET _analyze
    {
      "analyzer":"ik_max_word",
      "text": ["中国共产党"]
    }
    

5、 如果想将“狂神说”组成一个词不被拆分;

这种自己需要的词,需要自己加到我们的分词器的字典中!

在ES->plugins->ik(自己解压IK文件名)->config->IKAnalyzer.cfg.xml

<?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">lq.dic</entry>
	 <!--用户可以在这里配置自己的扩展停止词字典-->
	<entry key="ext_stopwords"></entry>
	<!--用户可以在这里配置远程扩展字典 -->
	<!-- <entry key="remote_ext_dict">words_location</entry> -->
	<!--用户可以在这里配置远程扩展停止词字典-->
	<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

以后的话,我们需要自己配置分词,就在自己定的dic文件中进行配置即可!

然后在同级目录下创建xxx.dic文件,将自己组的词放入,重启ES;

效果:

ElasticSearch狂神说笔记_第33张图片

以后的话,我们需要自己配置分词,就在自己定的dic文件中进行配置即可!



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张图片

那么name这个字段用不用指定类型呢,毕竟我们关系型数据库是需要执行类型的啊!

  • 字符串类型
    text、keyword
  • 数值类型
    long、integer、short、byte、double、float、half float、scaled float
  • 日期类型
    date
  • 布尔值类型
    boolean
  • 二进制类型
    binary
  • 等等…

4、指定字段的类型
ElasticSearch狂神说笔记_第36张图片
ElasticSearch狂神说笔记_第37张图片

2、获取索引

ElasticSearch狂神说笔记_第38张图片
如果自己的文档字段没有指定,那么es就会给我们默认配置字段类型!
type的默认值:_doc

3、更新索引

  • 可以使用put命令进行覆盖:
PUT /test2
{
  "mappings": {
    "properties": {
      "name":{
        "type": "text"
      },
      "age":{
        "type": "long"
      },
      "birthday":{
        "type": "date"
      }
    }
  }
}
  • 也可以使用POST中的_update进行局部更新(8.0及其以上版本的写法)
POST /test3/_update/d1
{
  "doc":{
    "name":"狂神说Java123456"
  }
}

4、删除索引

通过DELETE命令实现删除、根据你的请求来判断是删除索引还是删除文档记录

DELETE /test1      # 请求到文档,就删除对应的文档;库就删除对应的库

复杂查询操作

精确匹配:

GET /kuangshen/_search
{
  "query": {
    "match": {
       "name":"狂神说"
    }
  }
}

补充:
ElasticSearch狂神说笔记_第39张图片

结果过滤:

GET /kuangshen/_search
{
  "query": {
    "match": {
       "name":"狂神说"
    }
  },
  "_source": ["name","desc"]
}

排序:

GET /kuangshen/_search
{
  "query": {
    "match": {
       "name":"狂神说"
    }
  },
  "_source": ["name","desc","age"],
  "sort":[
    {
      "age": {
        "order":"desc"
      }
    }
    ]
}

分页:

GET /kuangshen/_search
{
  "query": {
    "match": {
       "name":"狂神说"
    }
  },
  "_source": ["name","desc","age"],
  "sort":[
    {
      "age": {
        "order":"desc"
      }
    }
  ],
  "from": 0,
  "size":2
}

布尔值查询
must(and),所有的条件都要符合,相当于:where id =1 and name = xxx

GET /kuangshen/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "狂神说"
          }
        },
        {
          "match": {
            "age": 180
          }
        }
      ]
    }
  }
}

should(or),只要其中一个满足条件即可,where id =1 or name = xxx

GET /kuangshen/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "name": "狂神说"
          }
        },
        {
          "match": {
            "age": 18
          }
        }
      ]
    }
  }
}

过滤器:

GET /kuangshen/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "狂神说"
          }
        }
      ],
      "filter": [
        {
          "range": {
            "age": {
              "gte": 18,
              "lte": 100
            }
          }
        }
      ]
    }
  }
}

条件:大于等于18岁,下雨等于100岁;

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

精确查询!

term查询是直接通过倒排索引指定的词条精确查找的!
关于分词:

  • term:直接查询精确地
  • match:会使用分词器解析!(先分析文档,然后通过分析的文档进行查询!)
    - 两个类型text、keyword
    keyword类型的字段,且是term查询的时候不会被分词器解析
    ElasticSearch狂神说笔记_第40张图片
    ElasticSearch狂神说笔记_第41张图片

高亮搜索

ElasticSearch狂神说笔记_第42张图片






SpringBoot整合Elasticsearch


官方文档

地址:https://www.elastic.co/guide/en/elasticsearch/client/index.html
ElasticSearch狂神说笔记_第43张图片

ElasticSearch狂神说笔记_第44张图片
1、找到原生的依赖

<dependency>
    <groupId>org.elasticsearch.clientgroupId>
    <artifactId>elasticsearch-rest-high-level-clientartifactId>
    <version>7.17.10version>
dependency>

2、找对象
ElasticSearch狂神说笔记_第45张图片

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

配置基本的项目

  • pom依赖
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>

        <dependency>
            <groupId>co.elastic.clientsgroupId>
            <artifactId>elasticsearch-javaartifactId>
            <version>8.7.0version>
            <exclusions>
                <exclusion>
                    <artifactId>jakarta.json-apiartifactId>
                    <groupId>jakarta.jsongroupId>
                exclusion>
                <exclusion>
                    <artifactId>elasticsearch-rest-clientartifactId>
                    <groupId>org.elasticsearch.clientgroupId>
                exclusion>
            exclusions>
        dependency>
        <dependency>
            <groupId>org.elasticsearch.clientgroupId>
            <artifactId>elasticsearch-rest-clientartifactId>
            <version>8.7.0version>
        dependency>
        <dependency>
            <groupId>jakarta.jsongroupId>
            <artifactId>jakarta.json-apiartifactId>
            <version>2.1.2version>
        dependency>
        <dependency>
            <groupId>jakarta.json.bindgroupId>
            <artifactId>jakarta.json.bind-apiartifactId>
            <version>3.0.0version>
        dependency>
        <dependency>
            <groupId>org.eclipsegroupId>
            <artifactId>yassonartifactId>
            <version>3.0.3version>
            <exclusions>
                <exclusion>
                    <artifactId>jakarta.json-apiartifactId>
                    <groupId>jakarta.jsongroupId>
                exclusion>
                <exclusion>
                    <artifactId>jakarta.json.bind-apiartifactId>
                    <groupId>jakarta.json.bindgroupId>
                exclusion>
                <exclusion>
                    <artifactId>parssonartifactId>
                    <groupId>org.eclipse.parssongroupId>
                exclusion>
            exclusions>
        dependency>

es客户端的版本(与本地es保持一致)

注意: 在Es7.15版本之后,es官方将它的高级客户端RestHighLevelClient标记为弃用状态。同时推出了全新的java API客户端Elasticsearch Java API Client,该客户端也将在Elasticsearch8.0及以后版本中成为官方推荐使用的客户端。


配置客户端:

@Configuration
public class ESConfig {

    @Bean
    public ElasticsearchClient elasticsearchClient(){
        //创建低级客户端
        RestClient restClient = RestClient.builder(new HttpHost("localhost", 9200)).build();

        //使用Jackjson映射器创建传输层
        RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());

        //创建API客户端
        ElasticsearchClient client = new ElasticsearchClient(transport);
        return client;
    }
}

索引index的基本语法

1、创建索引

    @Autowired
    private ElasticsearchClient client;

    /**
     * 创建索引
     */
    @ResponseBody
    @RequestMapping("/createIndex")
    public String createIndex() throws IOException {
        //创建一个名为lqindex的索引
        CreateIndexResponse response = client.indices().create(c -> c.index("lqindex"));
        //响应状态
        boolean acknowledged = response.acknowledged();
        System.out.println("创建索引lqindex:" + acknowledged);
        return acknowledged+"";
    }
    

2、查询索引

    /**
     * 查询索引
     */
    @ResponseBody
    @RequestMapping("/queryIndex")
    public String queryIndex() throws IOException {
        //查询lqindex索引
        GetIndexResponse getIndexResponse = client.indices().get(c -> c.index("lqindex"));
        //查询结果
        Map<String, IndexState> result = getIndexResponse.result();
        return JSON.toJSONString(result);
    }
    

3、删除索引

    /**
     * 删除索引
     */
    @ResponseBody
    @RequestMapping("/delIndex")
    public String delIndex() throws IOException {
        //删除lqindex索引
        DeleteIndexResponse deleteIndexResponse = client.indices().delete(c -> c.index("lqindex"));
        //删除索引的响应结果
        boolean acknowledged = deleteIndexResponse.acknowledged();
        return JSON.toJSONString(acknowledged);
    }
    

文档document的使用

1、创建document

    /**
     * 创建文档
     */
    @ResponseBody
    @RequestMapping("/createDoc")
    public String createDoc() throws IOException {
        Person person = new Person();
        person.setId(101).setName("李斯").setBirthday(new Date());
        //向索引中添加数据
        CreateResponse createResponse = client.create(doc -> {
            return doc.index("lqindex").id("001").document(person);
        });
        Result result = createResponse.result();
        return JSON.toJSONString(result);
    }
    

2、查询document

    /**
     * 查文档
     */
    @ResponseBody
    @RequestMapping("/queryDoc")
    public String queryDoc() throws IOException {
        GetResponse<Person> response = client.get(doc -> doc.index("lqindex").id("001"), Person.class);
        Person source = response.source();
        return JSON.toJSONString(source);
    }
    

3、修改document

    /**
     * 修改文档
     */
    @ResponseBody
    @RequestMapping("/updateDoc")
    public String updateDoc() throws IOException {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("name","黎明");
        UpdateResponse<Person> update = client.update(doc -> doc.index("lqindex").id("001").doc(map), Person.class);
        Result result = update.result();
        return JSON.toJSONString(result);
    }
    

4、删除document

    /**
     * 删除文档
     */
    @ResponseBody
    @RequestMapping("/delDoc")
    public String delDoc() throws IOException {
        DeletResponse deleteResponse = client.delete(doc -> doc.index("lqindex").id("001"));
        Result result = deleteResponse.result();
        return JSON.toJSONString(result);
    }
  

5、文档的批量创建

    /**
     * 文档的批量创建
     *
     * @return
     * @throws IOException
     */
    @RequestMapping("/batchCreateDoc")
    public String batchCreateDoc() throws IOException {
        List<BulkOperation> list = new ArrayList<>();
        list.add(new BulkOperation.Builder().create(doc -> doc.document(new Student((byte) 12, "zhangsan")).id("001").index("lqindex")).build());
        list.add(new BulkOperation.Builder().create(doc -> doc.document(new Student((byte) 13, "zhangsan")).id("002").index("lqindex")).build());
        list.add(new BulkOperation.Builder().create(doc -> doc.document(new Student((byte) 14, "zhangsan")).id("003").index("lqindex")).build());
        BulkResponse bulkResponse = client.bulk(req -> req.index("lqindex").operations(list));
        List<BulkResponseItem> items = bulkResponse.items();
        return JSON.toJSONString(items);
        
    }

6、文档的批量删除

    /**
     * document的批量删除
     *
     * @return
     * @throws IOException
     */
    @RequestMapping("/batchDelDoc")
    public String batchDelDoc() throws IOException {
        List<BulkOperation> list = new ArrayList<>();
        list.add(new BulkOperation.Builder().delete(doc -> doc.id("001").index("lqindex")).build());
        list.add(new BulkOperation.Builder().delete(doc -> doc.id("002").index("lqindex")).build());
        list.add(new BulkOperation.Builder().delete(doc -> doc.id("003").index("lqindex")).build());
        BulkResponse bulkResponse = client.bulk(req -> req.index("lqindex").operations(list));
        List<BulkResponseItem> items = bulkResponse.items();
        return JSON.toJSONString(items);
    }
    

查询

1、全量查询

/**
     * 全量查询
     *
     * @return
     * @throws IOException
     */
    @RequestMapping("/allQuery")
    public String allQuery() throws IOException {
        SearchResponse<Student> search = client.search(builder -> {
            return builder.index("lqindex").query(q -> q.matchAll(m -> m));
        }, Student.class);
        HitsMetadata<Student> hitsMetadata = search.hits();
        List<Hit<Student>> hits = hitsMetadata.hits();
        for (Hit<Student> hit : hits) {
            System.out.println(JSON.toJSONString(hit));
        }
        return JSON.toJSONString(hits);
    }
    

2、分页查询

    /**
     * 分页查询
     *
     * @return
     * @throws IOException
     */
    @RequestMapping("/pageQuery")
    public String pageQuery() throws IOException {
        SearchResponse<Student> search = client.search(builder -> {
            return builder.index("lqindex").query(q -> q.matchAll(m -> m)).from(1).size(10);
        }, Student.class);
        HitsMetadata<Student> hitsMetadata = search.hits();
        List<Hit<Student>> hits = hitsMetadata.hits();
        for (Hit<Student> hit : hits) {
            System.out.println(JSON.toJSONString(hit));
        }
        return JSON.toJSONString(hits);
    }
    

3、排序

 /**
     * 排序
     *
     * @return
     * @throws IOException
     */
    @RequestMapping("/sortQuery")
    public String sortQuery() throws IOException {
        SearchResponse<Student> search = client.search(builder -> {
            return builder.index("lqindex").query(q -> q.matchAll(m -> m)).sort(s->s.field(f->f.field("id").order(SortOrder.Asc)));
        }, Student.class);
        HitsMetadata<Student> hitsMetadata = search.hits();
        List<Hit<Student>> hits = hitsMetadata.hits();
        for (Hit<Student> hit : hits) {
            System.out.println(JSON.toJSONString(hit));
        }
        return JSON.toJSONString(hits);
    }
    

4、条件查询(哪几个字段显示)

/**
     * 条件查询(哪几个字段显示)
     *
     * @return
     * @throws IOException
     */
    @RequestMapping("/conditionQuery")
    public String conditionQuery() throws IOException {
        SearchResponse<Student> search = client.search(builder -> {
            return builder.index("lqindex").query(q -> q.matchAll(m -> m)).source(b->b.filter(f->f.includes("id",
                    "name").excludes("")));
        }, Student.class);
        HitsMetadata<Student> hitsMetadata = search.hits();
        List<Hit<Student>> hits = hitsMetadata.hits();
        for (Hit<Student> hit : hits) {
            System.out.println(JSON.toJSONString(hit));
        }
        return JSON.toJSONString(hits);
    }
    

5、组合查询(强匹配,相当于sql中的and)

    /**
     * 组合查询(强匹配)
     *
     * @return
     * @throws IOException
     */
    @RequestMapping("/comMustQuery")
    public String comMustQuery() throws IOException {
        SearchResponse<Student> search = client.search(builder -> {
            return builder.index("lqindex").query(q -> q.bool(b -> b.must(m->m.match(ch->ch.field("name").query(
                    "zhangsna"))).must(m->m.match(ma->ma.field("age").query(18)))));
        }, Student.class);

        HitsMetadata<Student> hitsMetadata = search.hits();
        List<Hit<Student>> hits = hitsMetadata.hits();
        for (Hit<Student> hit : hits) {
            System.out.println(JSON.toJSONString(hit));
        }
        return JSON.toJSONString(hits);
    }

6、组合查询(弱匹配,,相当于sql中的or)

/**
     * 组合查询(弱匹配,相当于sql中的or)
     *
     * @return
     * @throws IOException
     */
    @RequestMapping("/comShouldQuery")
    public String comShouldQuery() throws IOException {
        SearchResponse<Student> search = client.search(builder -> {
            return builder.index("lqindex").query(q -> q.bool(b -> b.should(m->m.match(ch->ch.field("name").query(
                    "zhangsna"))).should(m->m.match(ma->ma.field("age").query(18)))));
        }, Student.class);

        HitsMetadata<Student> hitsMetadata = search.hits();
        List<Hit<Student>> hits = hitsMetadata.hits();
        for (Hit<Student> hit : hits) {
            System.out.println(JSON.toJSONString(hit));
        }
        return JSON.toJSONString(hits);
    }

7、范围查询

/**
     * 范围查询
     *
     * @return
     * @throws IOException
     */
    @RequestMapping("/rangeQuery")
    public String rangeQuery() throws IOException {
        SearchResponse<Student> search = client.search(builder -> {
            //gte大于等于,lte小于等于
            return builder.index("lqindex").query(q -> q.range(r->r.field("age").gte(JsonData.of(12)).lte(JsonData.of(28))));
        }, Student.class);

        HitsMetadata<Student> hitsMetadata = search.hits();
        List<Hit<Student>> hits = hitsMetadata.hits();
        for (Hit<Student> hit : hits) {
            System.out.println(JSON.toJSONString(hit));
        }
        return JSON.toJSONString(hits);
    }

8、模糊查询

你可能感兴趣的:(Java进阶,elasticsearch,搜索引擎,lucene)