狂神说Elasticsearch7.X学习笔记整理

Elasticsearch概述

一、什么是Elasticsearch?

Lucene简介

Lucene Logo

  • Lucene是一套用于全文检索搜寻开源程序库,由Apache软件基金会支持和提供

  • Lucene提供了一个简单却强大的应用程序接口(API),能够做全文索引和搜寻,在Java开发环境里Lucene是一个成熟的免费开放源代码工具

  • Lucene并不是现成的搜索引擎产品,但可以用来制作搜索引擎产品

  • Lucene是一套信息检索工具包! jar包!不包含搜索引擎系统!
    Lucene包含:索引结构!读写索引的工具!排序,搜索规则...工具类!等

    Lucene和ElasticSearch关系:
    简单来说,Elasticsearch是基于Lucene做了一些封装和**增强 **

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(REST风格的网络接口,是当下主流的API)来隐藏Lucene的复杂性,从而让全文搜索变得简单。

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.比如说有个大型商场集团, BI分析一下某某区域最近3年的用户消费金额的趋势以及用户群体的组成构成,产出相关的数张报表, 最近3年,每年消费金额呈现100%的增长,而且用户群体85%是高级白领。。。

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

总而言之,Elasticsearch就是提供高效、个性化检索需求的一种解决方案

ELK简介

ELK是Elasticsearch、Logstash、Kibana三大开源框架首字母大写简称。市面上也被成为Elastic Stack。

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

Logstash是ELK的中央数据流引擎,用于从不同目标(文件/数据存储/MQ )收集的不同格式数据,经过过滤后支持输出以到不同目的地(文件/MQ/redis/elasticsearch/kafka等)。

Kibana可以将es的数据通过友好的页面展示出来 ,提供实时分析的功能。

总结一下就是:收集清洗数据-->建立索引,储存-->Kibana分析

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

image-20210131094725452

二、其他搜索引擎

Solr简介

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

Solr可以独立运行在Jetty、Tomcat等这些Servlet容器中 , Solr索引的实现方法很简单,用POST方法向Solr服务器发送一个描述Field及其内容的XML文档,Solr根据xml文档添加、删除、更新索引。

列如:搜索name==dayceng<>

Solr 搜索只需要发送HTTP GET请求,然后对Solr返回xml、json等格式的查询结果进行解析,组织页面布局。Solr不提供构建UI的功能, Solr提供了一个管理界面,通过管理界面可以查询Solr的配置和运行情况。

solr是基于lucene开发企业级搜索服务器,实际上就是封装了lucene.

Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的文件,生成索引;也可以通过提出查找请求,并得到返回结果。

ES与Solr对比

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

image-20210129115554753

当建立实时索引时,Solr会产生IO阻塞,查询性能较差,此时ES具有明显优势

image-20210129115715020

随着搜索量的增加,Solr的劣势愈发明显,ES无明显变化

image-20210129120150760

总结

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安装

注意:java版本至少为JDK1.8或以上

一、安装

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

windows下解压即可使用

二、Elasticsearch目录介绍

bin 相关启动文件

config 配置文件

​ log4j2.properties 日志配置文件

​ jvm.options java虚拟机配置文件

​ elasticsearch.yml ES配置文件(默认端口:9200,这里在tpot中,docker默认分配的是1111,需要再映射到9200才行)

lib 相关jar包

logs 日志

modules 功能模块

plugins 插件

三、启动

双击bin下的elasticsearch.bat即可

image-20210129150734078

四、测试访问

访问其暴露的端口进行验证(http://127.0.0.1:9200/)

image-20210129150840763

五、安装可视化界面Elasticsearch-head

注:安装需要前置环境

1、请下载Node.js(https://nodejs.org/en/),并检查npm为较新的版本

2、安装npm淘宝镜像源(cnpm)

npm install -g cnpm --registry=https://registry.npm.taobao.org

​ 查看是否安装成功

cnpm -v

​ 出现以下信息即可

C:\Users\XXXX> cnpm -v

cnpm@5.1.1 (F:\Live\NODE\node_global\node_modules\cnpm\lib\parse_argv.js)
npm@5.6.0 (F:\Live\NODE\node_global\node_modules\cnpm\node_modules\npm\lib\npm.js)
node@8.9.1 (F:\Live\NODE\node.exe)
npminstall@3.2.1 (F:\Live\NODE\node_global\node_modules\cnpm\node_modules\npminstall\lib\index.js)
prefix=F:\Live\NODE\node_global
win32 x64 10.0.16299
registry=http://registry.npm.taobao.org

在ElasticSearch\elasticsearch-head-master即ES head目录下

下载依赖

cnpm install

image-20210131091020099

运行

npm run start

image-20210131091205063

访问http://localhost:9100/

image-20210131091312021

此时因为跨域访问(跨端口)导致集群无法连接,要通过配置elasticsearch.yml来解决

六、解决跨域问题

配置es,打开elasticsearch.yml文件,在最后一行加入(注意yalm语法,冒号后要加一个空格)

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

使用elasticsearch.bat重启es,连接成功

image-20210131092227531

注1:Linux下可能会因为进程问题启动失败

#查看elastic的进程号 并杀死

ps aux | grep elasticsearch 

kill -9 进程号 

#重启 -d 后台运行

./bin/elasticsearch -d

注2:Linux下eshead启动失败,提示9100端口占用

#查看占用端口的进程id

 lsof -i:9100 

#杀死进行

kill -9 4852

七、Kibana安装

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

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

注意:使用的ES版本要与Kibana的对应

下载完成解压,双击kibana.bat启动即可

image-20210131103309389

汉化

在Kibana目录下的config中修改Kibana.yml文件,最后一行加上

i18n.locale: "zh-CN"

重启即可

ES核心概念

概述

Elasticsearch是面向文档的一种数据库,这意味着其不再需要行列式的表格字段约束。

ES会存储整个构造好的数据或文档,然而不仅仅是储存数据,这使得文档中每个数据可以被标识,进而可以被检索。在ES中,执行index,search,sort或过滤文档等操作都不是传统意义上的行列式的数据。

ES从根本上对数据的不同思考方式也正是他能应对复杂数据结构的全文检索的原因之一。

关系型数据库与Elasticsearch的对比

以下数据格式均为JSON

Relational DB Elasticsearch
数据库(database) 索引(index)
表(tables) 类型(types,新版本中逐步弃用)
行(rows) 文档(documents)
字段(columns) 字段(file)

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

物理设计:
Elasticsearch在后台把每个索引划分成多个分片,每分分片可以在集群中的不同服务器间迁移(方便集群的搭建)

实际上只建立一个索引它自己也是一个集群,默认名称就是elasticsearch

image-20210202093954072

逻辑设计:
一个索引类型中,包含多个文档,如文档1 ,文档2。

当我们索引一篇文档时,可以通过这样的一个顺序找到它:

​ 索引-->类型-->文档ID

通过这个组合我们就能索引到某个具体的文档。

(注:ID不必是整数,实际上它是个字符串。)

文档

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

●自我包含,一篇文档同时包含字段和对应的值,也就是同时包含key:value

●可以是层次型的,一个文档中包含着文档,复杂的逻辑实体就是这么来的(即文档就是JSON格式的对象,可用fastjson进行自动转换自动)

●灵活的结构,文档不依赖预先定义的模式,我们知道关系型数据库中,要提前定义字段才能使用,在Elasticsearch中,对于字段是非常灵活的,有时候我们可以忽略该字段,或者动态的添加一个新的字段。

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

文档就是一条条打好标签的数据

举个例子:

user

1 xiaoming 22

2 liming 19

。。。

这是一个表,名称为user,里面的每一行就是一个文档,文档中包含着序号、名字、年龄等信息(有点像之前要使用TFIDF算法时做的那个设备文档)

类型

类型是文档的逻辑容器,就像关系型数据库一样,表格是行的容器。

类型中对于字段的定义称为映射,比如name可以映射为字符串类型。

我们说文档是无模式的,它们不需要拥有映射中所定义的所有字段,比如新增一个字段。那么elasticsearch是怎么做的呢?elasticsearch会自动的将新字段加入映射,但是这个字段的不确定它是什么类型,elasticsearch就开始猜,如果这个值是18 ,那么elasticsearch会认为它是整形。

但是elasticsearch也可能猜不对 ,所以最安全的方式就是提前定义好所需要的映射,这点跟关系型数据库殊途同归了,先定义好字段,然后再使用

类比MySQL中,建立一个表的时候需要设定的数据类型

image-20210202095941630

索引

索引是映射类型的容器, elasticsearch中的索引是一个非常大的文档集合(即数据库)。索引存储了映射类型的字段和其他设置。 然后它们被存储到了各个分片上了。我们来研究下分片是如何工作的。

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

image-20210202100254208

存在数据库的数据可以通过不同的分片放在不同的集群上

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

image-20210202100505894

上图是一个有3个节点的集群,可以看到主分片和对应的复制分片都不会在同一个节点内(比如主分片P0和主分片的复制分片P1分别在节点1/3,同样的分片Px在每个至少有一个),当某个节点挂掉了,数据也不至于丢失。

实际上,一个分片是一个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 X
To X X
forever
every
study X
day
good
up
to X
every

现在,我们试图搜索to forever,只需要查看每个词条在对应文档是否出现即可。这里to和forever在doc1里面都有,而doc2中to没有,所以搜索结果为:doc1的权重更大,即“to forever”更可能出现在doc1

term doc_1 doc_2
to X
forever
SUM 2 1

这里的“权重”,即为文档的score,es搜索完成会对分数进行自动统计

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

再举一个例子

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

image-20210202111236177

如果要搜索含有python标签的文章,那相对于查找所有原始数据而言,查找倒排索引后的数据将会快的多。只需要查看标签这一栏,然后获取相关的文章ID即可。比如这里搜索“Linux”就绝对不会出现1或者2

elasticsearch的索引和Lucene的索引对比

在elasticsearch中,索引(数据库)这个词被频繁使用。在elasticsearch中 ,索引被分为多个分片,每份分片是一个Lucene的索引。所以一个elasticsearch索引是由多个Lucene倒排索引组成的。(因为elasticsearch使用Lucene作为底层)

image-20210202112920334

如无特指,说起索引都是指elasticsearch的索引

IK分词器

什么是IK分词器?

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

IK提供了两个分词算法: ik. smart和ik_max_ word

其中ik_smart为最少切分, ik _max_word为最细粒度划分

安装IK分词器

1、下载

https://github.com/medcl/elasticsearch-analysis-ik

2、安装

解压后放入es的插件目录plugins下即可

image-20210202144827745

3、重启es加载插件

image-20210202145019120

可使用以下命令查看插件列表

elasticsearch-plugin list

4、启动Kibana测试

测试ik_smart(使用RESTful风格的语句发起GET请求,对我们提供的JSON数据进行分词)

GET _analyze
{
"analyzer": "ik_smart",
"text": ["新型冠状病毒"]
}

运行结果:

image-20210202150329532

测试ik _max _word

GET _analyze
{
"analyzer": "ik_max_word",
"text": ["新型冠状病毒"]
}

运行结果:最细粒度划分会把所有可能的组合都划分出来(划分方式由某个字典规定)

image-20210202150645756

问题:当遇到自造词时,拆分结果不是我们想要的

image-20210202151449769

这时需要把关键词加入字典

配置IK分词器

添加自定义字典

elasticsearch-7.6.1\plugins\ik\config

中可以找到配置文件IKAnalyzer.cfg.xml

image-20210202152120411

只需要在config目录下新建一个自己的.dic字典文件并录入IKAnalyzer.cfg.xml中然后重启es即可

image-20210202152518579

测试能够识别自定义词语

image-20210202153349063

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
{
请求体
}
PUT /test1/type/1
{
  "name": "xiaoming",
  "age": 13
}

image-20210203092727349

image-20210203110817742

注意:

​ 1、创建的索引名要小写

​ 2、es head中数据浏览不显示内容就换个浏览器试试

2、更新一个索引

修改索引依旧可以使用PUT,此时返回的版本号会增加,"result"会提示update,但如果漏了一些信息,原始信息就会丢失,故现在一般使用POST来更新索引

POST /test1/type1/1
{
 "doc":{
   "name": "张三"
 }
}

image-20210203115556670

image-20210203115639183

没有写age,它就会保持原样(如果用PUT的话age就直接没了)

3、删除一个索引

DELETE test1(索引名或文档记录ID)

4、指定类型

常用的字段类型有:

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

创建一个t2索引(或者说索引库)但不创建文档,此时称其为一个“规则”

image-20210203111936090

查看t2,里面没有值,后续可以往里面放数据

image-20210203112007717

通过GET可以查看规则信息

image-20210203112304214

GET请求很好用,除了规则,还可以查看索引、文档的信息

注:

1、新版本es中正在逐步弃用type,我们创建索引库的时候可以将原来的type换成_doc,这样es就会自动帮我们配置字段类型

如下面的新建的test3:

image-20210203113420834

2、查看默认配置命令 GET _cat/indices?v

可以使用这个命令查看集群健康状态等一些信息

image-20210203114043227

关于文档的操作

基本操作

1、添加数据

PUT /dayceng/user/1
{
  "name": "DAYceng",
  "age": "22",
  "desc": "如此生活三十年",
  "tags": ["穷","阿宅","脚本小子"]
}

2、查询(获取,GET)数据

image-20210205094004174

3、简单搜索(GET条件查询)

GET /dayceng/user/_search?q=name:条件

image-20210205095050550

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

(这里的"_score"代表匹配度,分值越高,匹配度越高)

说明:

image-20210205095252732

字段name,它的类型是keyword,此时进行搜索,分词器不会对类型为keyword的name进行分词(即如果你搜“丹”是不会返回“丹霞”的结果的),如果类型是text则可以查到

复杂操作(主要是搜索)

复杂搜索select(排序、分页、模糊/精准查询、高亮)

1、使用请求体查询

一般来说,我们进行搜索不是直接写条件搜索,而是需要构建一个JSON格式的请求体,这样可以设置更多参数以实现定制化的搜索

GET /dayceng/user/_search
{
  "query": {
    "match": {
      "name": "丹霞"
    }
  }
}

image-20210205105110638

如果有相似关键字的多个结果,他们的分数会有不同

image-20210205110206156

hits是我们比较关注的一部分,其中包含:

​ 索引和文档的信息

​ 查询的结果总数

​ 查询出来的具体的文档

​ 分数:用来判断哪个结果更加符合预期

通过hits我们可以把数据的信息遍历出来,让我们想要的结果优先显示出来

后面使用java操控es,所有的方法和对象就是这里的hits、source等key

2、请求体参数

我们通过在请求体后添加参数的方式实现一些自定义的操作

筛选结果

只返回特定结果

GET /dayceng/user/_search
{
  "query": {
    "match": {
      "name": "丹霞"
    }
  },
   "_source":["name","tags"]
}

image-20210205114109589

排序
GET /dayceng/user/_search
{
  "query": {
    "match": {
      "name": "丹霞"
    }
  },
  "sort": [
    {
      "age": {
        "order": "desc"
      }
    }
  ]
}

注意:排序只能用于数值类型,我这里的age是text类型,运行就会报错

image-20210205115918067

"Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [age] in order to load field data by uninverting the inverted index. Note that this can use significant memory."

把“age”换成“age.keyword”即可正常排序

image-20210205120324780

分页
GET /dayceng/user/_search
{
  "query": {
    "match": {
      "name": "丹霞在"
    }
  },
  "sort": [
    {
      "age.keyword": {
        "order": "desc"
      }
    }
  ],
   "from": 0,---从第几个数据开始
   "size": 2 ---返回几个数据

}

image-20210206093248369

过滤

使用filter参数即可

image-20210206094548128

​ gt:大于

​ gte:大于等于

​ lt:小于

​ lte:小于等于

​ (以上条件可混合使用)

3、布尔值查询

使用布尔值可进行多条件查询

must:设置的所有match都要匹配才会返回结果

must not:返回与设置条件相反的结果

should:满足条件之一即可返回结果

GET /dayceng/user/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "DAYceng"
          }
        },
        {
          "match": {
            "age": 22
          }
        }
      ]
    }
  }

}

image-20210206093144473

4、精确查询

term查询是直接使用倒排索引进行精确查询的

term与match的比较

​ ·term使用倒排索引直接进行精确查询

​ ·match则会使用分词器进行解析后再查询(先分析文档,在通过分析结果进行查询)

类型text与keyword的比较

text会使用分词器进行分词后再查询

image-20210206102310427

keyword不会拆分特定词语

image-20210206102247047

5、高亮查询

使用highlight参数

GET /dayceng/user/_search
{
  "query": {
    "match": {
      "name": "丹霞"
    }
  },
  "highlight": {
    "fields": {
      "name":{}
    }
  }
}

image-20210206104615060

在highlight中也可以自定义高亮标签

GET /dayceng/user/_search
{
  "query": {
    "match": {
      "name": "丹霞"
    }
  },
  "highlight": {
    "pre_tags": "<p class=key style='color:red'>", 
    "post_tags": "</p>", 
    "fields": {
      "name":{}
    }
  }
}

image-20210206105030939

Python-elasticsearch基本用法

官方文档:https://www.elastic.co/guide/en/elasticsearch/client/python-api/current/connecting.html#_getting_a_document

安装及初始化

使用pip安装即可

pip install elasticsearch
pip install elasticsearch[async]	#支持异步,可不安装

实例化es客户端

image-20210219115247238

实际上这里文档中给了三种创建客户端的方式,我们选择HTTP authentication方式(看起来清晰一些,当然你也可以用别的)实例化es对象

es = Elasticsearch(
    [
        {"host": "127.0.0.1", "port": 9200},
    ],
    http_auth=("username", "secret"),
    timeout=3600
)

ES提供了两种搜索的方式:  

  请求参数方式

  请求体方式(带body 的那种查询,把查询的内容放入body中,会造成一定的开销,但是易于理解)

这里我们使用请求体方式进行搜索

配置一个body

body = {
    "settings": {
        "number_of_shards": 3,
        "number_of_replicas": 2
    },
    "mappings":{
        # "_doc":{
        "properties":{
            "id":{
                "type":"integer",
            },
            "text": {
                "type": "text",
                "analyzer": "ik_max_word",  #指定ik分词器,适用中文分词。
                "index":False
            },
            "userId": {
                "type": "long",
            },
            "reprinted": {
                "type": "keyword",
            },
        }

注:可以看到,body中实际上就是之前我们使用请求体参数搜索时设置的一些东西

单一操作

增加

create

必须指定待查询的idnex、type、id和查询体body;缺一不可,否则报错

es.indices.create(index = "testpy", body = body)

index 

相比于create,index的用法就相对灵活很多;id并非是一个必选项,如果指定,则该文档的id就是指定值,若不指定,则系统会自动生成一个全局唯一的id赋给该文档。

es.index(index = "testpy", doc_type = "_doc", id = 1, body = {"id":1, "name":"小明"})

删除

  delete:删除指定index、type、id的文档

es.indices.delete(index = 'test')

查找

  get:获取指定index、type、id所对应的文档

es.get(index="testpy", id=2)

更新

  update:跟新指定index、type、id所对应的文档

es.update(index='testpy', doc_type='_doc', id='2', body={待更新字段})

批量操作

查询

search:查询满足条件的所有文档,没有id属性,且index,type和body均可为None。 body的语法格式必须符合DSL格式

es.search(index = "test", doc_type = "_doc", body = query)

复合查询语句

query = {'query': {'match_all': {}}}# 查找所有文档
query = {'query': {'term': {'name': 'jack'}}}# 查找名字叫做jack的所有文档
query = {'query': {'range': {'age': {'gt': 11}}}}# 查找年龄大于11的所有文档
allDoc = es.search(index='indexName', doc_type='typeName', body=query)

删除

delete_by_query

query = {'query': {'match': {'sex': 'famale'}}}# 删除性别为女性的所有文档
query = {'query': {'range': {'age': {'lt': 11}}}}# 删除年龄小于11的所有文档
es.delete_by_query(index='indexName', body=query, doc_type='typeName')

更新

update_by_query

query = {
            "script": {
            "lang": "painless",
            # "inline": "if (ctx._source.test_code == null) {ctx._source.test_code= '02'}"
            "inline": "ctx._source.kw_sourceType= 'trueTime'"   #新增字段kw_sourceType值为trueTime
              }
            }
res = es.update_by_query(index="hot_rank", doc_type="baidu_hot_search_rank", body=query)

完整测试工程代码

from elasticsearch import Elasticsearch
from datetime import datetime
#from elasticsearch import AsyncElasticsearch

#es = Elasticsearch(host="localhost", port=9200)

es = Elasticsearch(
    [
        {"host": "127.0.0.1", "port": 9200},
    ],
    http_auth=("username", "secret"),
    timeout=3600
)
body = {
    "settings": {
        "number_of_shards": 3,
        "number_of_replicas": 2
    },
    "mappings":{
        # "_doc":{
        "properties":{
            "id":{
                "type":"integer",
            },
            "text": {
                "type": "text",
                "analyzer": "ik_max_word",  #指定ik分词器,适用中文分词。
                "index":False
            },
            "userId": {
                "type": "long",
            },
            "reprinted": {
                "type": "keyword",
            },
        }
        # }
    }
}
#创建 index
#es.indices.create(index = "testpy", body = body)
#删除 index
#es.indices.delete(index = 'test')

#插入数据
#es.index(index = "testpy", doc_type = "_doc", id = 1, body = {"id":1, "name":"小明"})
#可以不用指定id,create会自动添加id。
#es.create(index="testpy", doc_type = "_doc",id = 2, body = {"id":2, "name":"小红"})

'''doc = {
    'author': 'author_name',
    'text': 'Interensting content...',
    'timestamp': datetime.now(),
}'''

res = es.get(index="testpy", id=2)
#es.search(index = "test", doc_type = "_doc", body = query)
print(res['_source'])

posted @ 2021-05-11 15:31  dayceng  阅读(2445)  评论(0编辑  收藏  举报