Elasticsearch初学习,收集整理资料

一、概述
1.1 简介
The Elastic Stack, 包括 Elasticsearch、 Kibana、 Beats 和 Logstash(也称为 ELK Stack)。能够安全可靠地获取任何来源、任何格式的数据,然后实时地对数据进行搜索、分析和可视化。
Elaticsearch,简称为 ES, ES 是一个开源的高扩展的分布式全文搜索引擎, 是整个 ElasticStack 技术栈的核心。
它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理 PB 级别的数据。

1.2 RESTful & JSON
REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。 Web 应用程序最重要的 REST 原则是,客户端和服务器之间的交互在请求之间是无状态的。
在服务器端,应用程序状态和功能可以分为各种资源。资源是一个有趣的概念实体,它向客户端公开。资源的例子有:应用程序对象、数据库记录、算法等等。每个资源都使用 URI(Universal Resource Identifier) 得到一个唯一的地址。所有资源都共享统一的接口,以便在客户端和服务器之间传输状态。使用的是标准的 HTTP 方法,比如 GET、 PUT、 POST 和DELETE。
在 REST 样式的 Web 服务中,每个资源都有一个地址。资源本身都是方法调用的目标,方法列表对所有资源都是一样的。这些方法都是标准方法,包括 HTTP GET、 POST、PUT、 DELETE,还可能包括 HEAD 和 OPTIONS。简单的理解就是,如果想要访问互联网上的资源,就必须向资源所在的服务器发出请求,请求体中必须包含资源的网络路径,以及对资源进行的操作(增删改查)。
REST 样式的 Web 服务若有返回结果,大多数以JSON字符串形式返回。(使用Postman客户端测试)

1.3 全文搜索引擎
指的是目前广泛应用的主流搜索引擎。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。

1.4 倒排索引
Elasticsearch 是面向文档型数据库,一条数据在这里就是一个文档。 为了方便大家理解,我们将 Elasticsearch 里存储文档数据和关系型数据库 MySQL 存储数据的概念进行一个类比。ES 里的 Index 可以看做一个库,而 Types 相当于表, Documents 则相当于表的行。这里 Types 的概念已经被逐渐弱化, Elasticsearch 6.X 中,一个 index 下已经只能包含一个type, Elasticsearch 7.X 中, Type 的概念已经被删除了。
Elasticsearch 使用一种称为 倒排索引 的结构,它适用于快速的全文搜索。一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表。
例如,假设我们有两个文档,每个文档的 content 域包含如下内容:
1.The quick brown fox jumped over the lazy dog
2.Quick brown foxes leap over lazy dogs in summer
为了创建倒排索引,我们首先将每个文档的 content 域拆分成单独的 词(我们称它为 词条 或 tokens ),创建一个包含所有不重复词条的排序列表,然后列出每个词条出现在哪个文档。结果如下所示:

Term Doc_1 Doc_2

Quick | | X
The | X |
brown | X | X
dog | X |
dogs | | X
fox | X |
foxes | | X
in | | X
jumped | X |
lazy | X | X
leap | | X
over | X | X
quick | X |
summer | | X
the | X |

现在,如果我们想搜索 quick brown ,我们只需要查找包含每个词条的文档:
Term Doc_1 Doc_2

brown | X | X
quick | X |

Total | 2 | 1
两个文档都匹配,但是第一个文档比第二个匹配度更高。如果我们使用仅计算匹配词条数量的简单 相似性算法 ,那么,我们可以说,对于我们查询的相关性来讲,第一个文档比第二个文档更佳。

1.5 服务搭建
windows单机版:

下载解压,双击bin目录下bat脚本运行即可

linux单机版及集群(非重点,不详细介绍,详情见链接):
https://www.jianshu.com/p/941c9797923e
https://blog.csdn.net/csdn_20150804/article/details/105474605
使用docker搭建集群:
https://blog.csdn.net/qq_36364955/article/details/115909204
(拉取镜像:docker pull elasticsearch:7.16.2
单节点启动:docker run -d --name es -p 9200:9200 -p 9300:9300 -e “discovery.type=single-node” elasticsearch:7.16.2)

elasticsearch-head插件安装:
1.通过docker安装(推荐)
2.通过chrome插件安装(推荐)

二、使用(HTTP请求)
2.1 索引-创建
对比关系型数据库,创建索引就等同于创建数据库。
在 Postman 中,向 ES 服务器发 PUT 请求 : http://127.0.0.1:9200/shopping
(重复发送会报错误信息)

2.2 索引-查询 & 删除
2.2.1 查看所有索引
在 Postman 中,向 ES 服务器发 GET 请求 : http://127.0.0.1:9200/_cat/indices?v

这里请求路径中的_cat 表示查看的意思, indices 表示索引,?v表示启用表头,所以整体含义就是查看当前 ES服务器中的所有索引,就好像 MySQL 中的 show tables 的感觉。

返回结果:

2.2.2 查看单个索引
在 Postman 中,向 ES 服务器发 GET 请求 : http://127.0.0.1:9200/shopping
返回结果:

2.2.3 删除索引
在 Postman 中,向 ES 服务器发 DELETE 请求 : http://127.0.0.1:9200/shopping

2.3 映射-创建
为了能够将时间域视为时间,数字域视为数字,字符串域视为全文或精确值字符串, Elasticsearch 需要知道每个域中数据的类型。这个信息包含在映射中。Elasticsearch 支持如下简单域类型:
字符串: text, keyword
整数 : byte, short, integer, long
浮点数: float, double
布尔型: boolean
日期: date
在 Postman 中,向 ES 服务器发 PUT 请求 : http://127.0.0.1:9200/shopping/_mapping
请求体:
{
“properties”: {
“title”:{
“type”: “keyword”, // keyword类型则此字段不分词
“index”: true // index若为false则无法使用此字段检索
},
“price”:{
“type”: “integer”,
“index”: true
},
“desc”:{
“type”: “text”,
“index”: true
},
“date”:{
“type”: “date”,
“index”: true
}
}
}
域还有一个重要的属性是 index,它控制怎样索引字符串。可以是下面三个值:
analyzed
首先分析字符串,然后索引它。换句话说,以全文索引这个域。
not_analyzed
索引这个域,所以它能够被搜索,但索引的是精确值。不会对它进行分析。
no
不索引这个域。这个域不会被搜索到。

2.4 文档-创建
假设索引已经创建好了,接下来我们来创建文档,并添加数据。这里的文档可以类比为关系型数据库中的表数据,添加的数据格式为 JSON 格式。
在 Postman 中,向 ES 服务器发 POST 请求 : http://127.0.0.1:9200/shopping/_doc,请求体JSON内容为:
{
“title”:“小米手机”,
“price”:3999,
“desc”:“http://www.xiaomi.com/xm.jpg”,
“date”:“2014-02-12”
}
(我们也可以指定ID进行创建,http://127.0.0.1:9200/shopping/_doc/1,请求体同上,且明确主键的情况下,请求方式可以为PUT 请求)

2.5 查询-主键查询 & 全查询
查看文档时,需要指明文档的唯一性标识,类似于 MySQL 中数据的主键查询。
2.5.1 主键查询
在 Postman 中,向 ES 服务器发 GET 请求 : http://127.0.0.1:9200/shopping/_doc/1
2.5.2 全查询
查看索引下所有数据,向 ES 服务器发 GET 请求 : http://127.0.0.1:9200/shopping/_search

2.6 全量修改 & 局部修改 & 删除
和新增文档一样,输入相同的 URL 地址请求,如果请求体变化,会将原有的数据内容覆盖。
2.6.1 全量修改
在 Postman 中,向 ES 服务器发 POST 请求 : http://127.0.0.1:9200/shopping/_doc/1
请求体JSON内容为:

{
“title”:“华为手机”,
“price”:1299,
“desc”:“华为手机123”,
“date”:“2015-02-01”
}
2.6.2 局部修改
修改数据时,也可以只修改某一给条数据的局部信息。
在 Postman 中,向 ES 服务器发 POST 请求 : http://127.0.0.1:9200/shopping/_update/1
请求体JSON内容为:
{
“doc”: {
“price”:3999
}
}

2.6.3 删除文档
删除一个文档不会立即从磁盘上移除,它只是被标记成已删除(逻辑删除)。
在 Postman 中,向 ES 服务器发 DELETE 请求 : http://127.0.0.1:9200/shopping/_doc/1

2.7 深入查询
查询表达式(Query DSL)是一种非常灵活又富有表现力的 查询语言。 Elasticsearch 使用它可以以简单的 JSON 接口来展现 Lucene 功能的绝大部分。在你的应用中,你应该用它来编写你的查询语句。它可以使你的查询语句更灵活、更精确、易读和易调试。
要使用这种查询表达式,只需将查询语句传递给 query 参数:

GET /_search
{
“query”: YOUR_QUERY_HERE
}

2.7.1 查询与过滤
Elasticsearch 使用的查询语言(DSL)拥有一套查询组件,这些组件可以以无限组合的方式进行搭配。这套组件可以在以下两种情况下使用:过滤情况(filtering context)和查询情况(query context)。

当使用于 过滤情况 时,查询被设置成一个“不评分”或者“过滤”查询。即,这个查询只是简单的问一个问题:“这篇文档是否匹配?”。回答也是非常的简单,yes 或者 no ,二者必居其一。

当使用于 查询情况 时,查询就变成了一个“评分”的查询。和不评分的查询类似,也要去判断这个文档是否匹配,同时它还需要判断这个文档匹配的有 多好(匹配程度如何)。

性能差异:
  过滤查询(Filtering queries)只是简单的检查包含或者排除,这就使得计算起来非常快,并且结果会被缓存到内存中以便快速读取,所以有各种各样的手段来优化查询结果。
评分查询(Scoring queries)不仅仅要找出匹配的文档,还要计算每个匹配文档的相关性,计算相关性使得它们比不评分查询费力的多。同时,查询结果并不缓存。

一句话总结:
过滤查询,不需要计算相关度分数,不需要按照相关度分数进行排序,同时还有内置的自动cache最常使用filter的数据。
评分查询,要计算相关度分数,按照分数进行排序,而且无法cache结果。

2.7.2 查询关键字
(1)match_all 查询
match_all 查询简单的匹配所有文档。在没有指定查询方式时,它是默认的查询:
{
“match_all”: {}
}
检索出的数据被认为具有相同的相关性,所以都将获得分值为 1 的中性 _score,它也经常与 filter 结合使用。

(2)match 查询
无论在任何字段上进行的是全文搜索还是精确查询,match 查询都是可用的标准查询。 如果你在一个全文字段(text)上使用 match查询,在执行查询前,它将用正确的分析器(ES标准分析器是中文单字分词、英文单词分词)去分析查询字符串:
{ “match”: { “desc”: “华为” }}

如果在一个精确值的字段上使用match,例如数字、日期、布尔或者一个 not_analyzed 字符串字段,那么它将会精确匹配给定的值:
{ “match”: { “price”: 2999 }}
{ “match”: { “date”: “2019-09-19” }}
{ “match”: { “title”: “小米11” }}
不过对于精确值的查询,一般会使用 filter 语句来取代 query,因为 filter 将会被缓存。此外还有match_phrase短语匹配,它在查询时也会进行分词,但必须全部匹配且相对顺序一致。

(3)multi_match 查询
multi_match 查询可以在多个字段上执行相同的 match 查询:
{
“multi_match”: {
“query”: “小米11”,
“fields”: [ “title”, “desc” ]
}
}

(4)range 查询
range 查询找出那些落在指定区间内的数字或者时间:
{
“range”: {
“price”: {
“gte”: 1999,
“lt”: 4000
}
}
}
被允许的操作符如下:
gt 大于
gte 大于等于
lt 小于
lte 小于等于

(5)term 查询
term 查询被用于精确值匹配,这些精确值可能是数字、时间、布尔或者那些 not_analyzed 的字符串:
{ “term”: { “price”: 2999 }}
{ “term”: { “date”: “2019-09-19” }}
{ “term”: { “title”: “小米11” }}
term 查询对于输入的文本不分析,它会将给定的值进行精确查询。

(6)terms 查询
terms 查询和 term 查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件:
{ “terms”: { “title”: [ “小米11”, “华为P20”] }}
和 term 查询一样,terms 查询对于输入的文本也不分析,它查询那些精确匹配的值。

(7)exists查询和 missing查询
exists 查询和 missing 查询(ES 5及之后的版本已被弃用)被用于查找那些指定字段中有值 (exists) 或无值 (missing) 的文档。这与SQL中的 IS_NULL (missing) 和 NOT IS_NULL (exists) 在本质上具有共性:
{
“exists”: {
“field”: “title”
}
}
(8)合并查询语句
可以使用 bool 查询来实现查询语句的合并,这种查询将多查询组合在一起,成为用户自己想要的布尔查询。

它接收以下参数:

must 文档 必须 匹配这些条件才能被包含进来。

must_not 文档 必须 不匹配这些条件才能被包含进来。

should 如果满足这些语句中的任意语句,将增加 _score ,否则,无任何影响。它们主要用于修正每个文档的相关性得分。

filter 必须 匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。

(9)基础组合
下面是我们看到的第一个包含多个查询的查询,每一个子查询都独自地计算文档的相关性得分。一旦他们的得分被计算出来, bool 查询就将这些得分进行合并并且返回一个代表整个布尔操作的得分。
{
“bool”: {
“must”: { “match”: { “desc”: “小米” }},
“must_not”: { “match”: { “title”: “小米11” }},
“should”: [
{ “term”:{ “price”: 2999 }},
{ “range”: { “date”: { “gte”: “2018-01-01” }}}
]
}
}
tag:如果没有 must 语句,那么至少需要能够匹配其中的一条 should 语句。但如果存在至少一条 must 语句,则对 should 语句的匹配没有要求。

(10)增加带过滤器的查询
如果我们不想因为文档的时间而影响得分,可以用 filter 语句来重写前面的例子,把range 查询从 should 中移到 filter 中:
{
“bool”: {
“must”: { “match”: { “desc”: “小米” }},
“must_not”: { “match”: { “title”: “小米MIX3” }},
“should”: [
{ “term”:{ “price”: 2999 }} ],
“filter”: {
“range”: { “date”: { “gte”: “2018-01-01” }}
}
}
}
通过将 range 查询移到 filter 语句中,我们将它转成不评分的查询,将不再影响文档的相关性排名。
由此可见,可以使用各种对 filter 查询有效的优化手段来提升性能。所有查询都可以借鉴这种方式。将查询移到 bool 查询的 filter 语句中,这样它就自动的转成一个不评分的 filter 了。

如果你需要通过多个不同的标准来过滤你的文档,bool 查询本身也可以被用做不评分的查询。简单地将它放置到 filter 语句中并在内部构建布尔逻辑:
{
“bool”: {
“must”: { “match”: { “desc”: “小米” }},
“must_not”: { “match”: { “title”: “小米MIX3” }},
“should”: [
{ “term”:{ “price”: 2999 }} ],
“filter”: {
“bool”: {
“must”: { “match”: { “title”: “小米11” }},
“should”: [
{ “term”:{ “price”: 3999 }},
{ “range”: { “date”: { “gte”: “2018-01-01” }}}
]
}
}
}
}
(11)constant_score 查询
constant_score 查询被经常用于你只需要执行一个 filter 而没有其它查询(例如,评分查询)的情况下。
可以使用它来取代只有 filter 语句的 bool 查询。在性能上是完全相同的,但对于提高查询简洁性和清晰度有很大帮助。
{
“constant_score”: {
“filter”: {
“match”: { “desc”: “小米” }
}
}
}

(12)模糊查询(prefix、wildcard、regexp、fuzzy)
prefix(前缀查询):
prefix 查询是一个词级别的底层的查询,它不会在搜索之前分析查询字符串,它假定传入前缀就正是要查找的前缀。
默认状态下, prefix 查询不做相关度评分计算,它只是将所有匹配的文档返回,并为每条结果赋予评分值 1 。它的行为更像是过滤器而不是查询。 prefix 查询和 prefix 过滤器这两者实际的区别就是过滤器是可以被缓存的,而查询不行。
{
“prefix”: {
“title”: “小米”
}
}

wildcard & regexp(通配符 & 正则表达式查询):
与 prefix 前缀查询的特性类似, wildcard 通配符查询也是一种底层基于词的查询,与前缀查询不同的是它允许指定匹配的正则式。它使用标准的 shell 通配符查询: ? 匹配任意字符, * 匹配 0 或多个字符。wildcard 和 regexp 查询的工作方式与 prefix 查询完全一样,它们也需要扫描倒排索引中的词列表才能找到所有匹配的词,然后依次获取每个词相关的文档 ID ,与 prefix 查询的唯一不同是:它们能支持更为复杂的匹配模式。
prefix 、 wildcard 和 regexp 查询是基于词操作的,如果用它们来查询 analyzed 字段,它们会检查字段里面的每个词,而不是将字段作为整体来处理。三者查询性能都较为低下。
{ “wildcard”: { “title”: “iphone?” }}
{ “regexp”: { “title”: “华为[A-Z]20” }}

fuzzy(纠错查询):
fuzzy 查询是一个词项级别的查询,所以它不做任何分析。它通过某个词项以及指定的 fuzziness(纠错距离) 查找到词典中所有的词项。 fuzziness 默认设置为 AUTO 。
“fuzzy”: {
“title”: {
“value”: “米1”,
“fuzziness”: 2
}
}
(13)聚合查询
聚合查询aggs允许使用者对 es 文档进行统计分析,类似与关系型数据库中的 group by,其中有多种的聚合方式,例如取最大值max、平均值avg等等。
“aggs”:{//聚合操作
// “price_group”:{//名称,随意起名
// “terms”:{//分组
“price_avg”:{//名称,随意起名
“avg”:{//求平均
“field”:“price”
}
}
}
(14)排序
Elasticsearch默认是相关性排序的,为了按照相关性来排序,需要将相关性表示为一个数值。在 Elasticsearch 中, 相关性得分 由一个浮点数进行表示,并在搜索结果中通过 _score 参数返回, 默认排序是 _score 降序。
按字段排序:我们可以使用 sort 参数进行实现。
“query” : {
“bool” : {
“must” : { “match_phrase” :
{ “desc” : “小米” }}
}
},
“sort”: { “date”: { “order”: “desc” }}

(15)分页查询
分页查询要在查询请求体里使用size和from关键字,size是返回数量,from是跳过多少数据。
{
“from”: 4,
“size”: 2
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值