前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Elasticsearch7教程

Elasticsearch7教程

作者头像
Remember_Ray
发布2021-04-05 11:17:07
4K0
发布2021-04-05 11:17:07
举报
文章被收录于专栏:Ray学习笔记

Elasticsearch7教程

Elasticsearch快速入门,掌握这些刚刚好!

前序

Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。Elasticsearch用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。官方客户端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和许多其他语言中都是可用的。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr,也是基于Lucene。

正排索引和倒排索引

导读

索引(index)作为一种具备各种优势的数据结构,被大量应用在数据检索领域。其中倒排索引数据结构在搜索引擎框架中扮演着非常重要的角色。

假设我们有网页1和网页2:

  • 网页1:厦门SEO顾问潇湘驭文为您提供厦门SEO培训服务。
  • 网页2:SEO是一门艺术。

正排索引

经过搜索引擎初步分词之后,网页1和2的正向索引如下图所示:

假设使用正向索引,那么当你搜索SEO的时候,搜索引擎必须检索网页中的每一个关键词,假设一个网页中包含成千上百个关键词,可想而知,会造成大量的资源浪费。于是倒排索引应运而生。

倒排索引

倒排索引是相对正向索引而言的,你也可以将其理解为逆向索引。它是一种关键词与网页一一对应的数据结构。如下图所示:

从上图可以一目了然,倒排索引可以直接参与排名。

比如你搜索“SEO”,搜索引擎可以快速检索出包含“SEO”搜索词的网页1和网页2,为后续的相关度和权重计算奠定基础,从而大大加快了返回搜索结果的速度。

下载及配置

下载

软件名

下载地址

Elasticsearch

https://www.elastic.co/cn/start

Kibana

https://www.elastic.co/cn/start

Logstash

https://www.elastic.co/cn/downloads/logstash

解决跨域

当使用 elasticsearch-head 会存在跨域问题。

修改 *Elasticsearch *配置文件 ..\elasticsearch-7.10.1\config\elasticsearch.yml

代码语言:javascript
复制
# 解决端口 9100 访问 9200 跨域问题
http.cors.enabled: true
http.cors.allow-origin: "*"

中文显示

当使用 Kibana 可以设置成中文

修改 Kibana 配置文件 ..\kibana-7.10.1-windows-x86_64\config\kibana.yml

代码语言:javascript
复制
# 改成中文
i18n.locale: "zh-CN"

Elasticsearch的基本概念

shard(分片)

单台机器(节点)无法存储大量的索引数据, ES可以把一个完整的索引分成多个分片, 分布到不同的节点上, 从而构成分布式索引. 每个分片都是一个Lucene实例, 也就是说每个分片底层都有一个单独的Lucene提供独立的索引和检索服务, 它们可以托管在集群的任一节点上. 单个Lucene中存储的索引文档最大值为 lucene-5843, 极限是2147483519(=integer.max_value - 128) 个文档. 可使用_cat/shards API 监控分片的大小.

分片好处

允许水平切分/扩展集群容量; 可在多个分片上进行分布式的、并行的操作, 提高系统的性能和吞吐量.

注意事项

分片的数量只能在创建索引前指定, 创建索引后不能修改. 5.x 版本默认不能通过配置文件elasticsearch.yml定义分片个数.

replica(副本)

ES支持为每个Shard创建多个副本, 相当于索引数据的冗余备份. 分片有Primary Shard(主分片)、Replica Shard(副本分片), 建立索引时, 系统会先将索引存储在主分片中, 然后再将主分片中的索引复制到不同的副本中.

副本的重要性

  1. 解决单点问题, 提高可用性和容错性: 某个节点失败时服务不受影响, 可以从副本中恢复;
  2. 提高查询效率和查询时的吞吐量: 搜索可以在所有的副本上并行执行, 提高了服务的并发量.

注意事项

主分片在建立索引时设置, 后期不能修改; 主分片和副本分片不能存储在同一个节点中 —— 无法保证高可用. 5.x版本中, 默认主分片为5个, 默认副本分片数为1个, 即每个主分片各有1个副本分片(共5个副本分片); 可随时修改副本分片的数量. 默认情况下, 每个索引共有 5 primary shard + 5 * 1 replica shard = 10 shard. 集群中至少要有2个节点, 这是最少的高可用配置.

index(索引)

索引是具有相似结构的文档的集合, 等同于Solr中的集合, 比如可以有一个商品分类索引, 订单索引. 每个索引都要有唯一的名称, 名称要小写, 通过索引名称来执行索引、搜索、更新和删除等操作. 一个集群中可以有任意多个索引, 只要保证名称不同即可.

document(文档)

文档是存储在ES中的一个个JSON格式的字符串, 是ES索引中的最小数据单元, 由field(字段)构成.

type(类型)

type是index的逻辑分类, 在ES 6.x版本之前, 每个索引中可以定义一个或多个type, 而在6.X版本之后, 一个index中只能定义一个type. 一种type一般被定义为具有一组公共field的document, 比如对博客系统中的数据建立索引, 可以定义用户数据type, 博客数据type, 评论数据type, 也就是每个document都必须属于某一个具体的type, 也就是说每个document都有_type属性.

mapping(映射)

类似于关系数据库中的Table结构, 每个index都有一个映射: 定义索引中每个字段的类型. 所有文档在写进索引之前都会先进行分析, 如何对文本进行分词、哪些词条又会被过滤, 这类行为叫做映射(mapping). 映射可以提前定义, 也可以在第一次存储文档时自动识别. 一般由用户自己定义规则. 类似于Solr中schema.xml约束文件的作用.

field(字段)

字段可以是一个简单的值(如字符串、数字、日期), 也可以是一个数组, 还可以嵌套一个对象或多个对象. 字段类似于关系数据库中表数据的列, 每个字段都对应一个类型. 可以指定如何分析某一字段的值, 即对field指定分词器.

概念关系图

ES的索引中, 各概念的关系为: Field –> Document –> Type –> Index, 索引结构图如下:

注意:在7.0之前,一个Index可以创建多个类型,从7.0开始,一个索引只能创建一个类型,也就是 _doc

与关系型数据库的对比:

Elasticsearch

RDBMS

Index(索引)

DataBase(数据库)

Type(类型)

Table(表)

Document(文档)

Row(行)

Field(字段)

Column(列)

Mapping(映射)

Schema(约束)

Everything is indexed(存储的都是索引)

Index(索引)

Query DSL(ES独特的查询语言)

SQL(结构化查询语言)

RestAPI

CRUD 操作

代码语言:javascript
复制
# 查询 movies 的数据
GET movies/_search

# 查询 movies 的数量
GET movies/_count

# 查看所有的索引
GET _cat/indices

# 查询id为24的数据
GET movies/_doc/24
代码语言:javascript
复制
# 添加新的文档,如果没有指定id,ES会自动生成id
POST users/_doc
{
  "firstname": "will",
  "lastname": "smith"
}


# 添加id为2的文档,ES不会自动生成id
POST users/_doc/2
{
  "firstname": "will2",
  "lastname": "smith2"
}

# 查询 users 的数据
GET users/_search

# 创建id为2的文档,如果索引中已经存在相同的id,会报错,创建失败;如果不存在相同的id,则创建成功
POST users/_create/2
{
  "firstname": "will2",
  "lastname": "smith2"
}

# 更新id为2的文档,更新指定field
POST users/_update/2
{
  "doc": {
    "firstname": "jack",
    "lastname": "well"
  }
}

# 更新id为2的文档,添加一个field
POST users/_update/2
{
  "doc": {
    "age": 30
  }
}

# 删除id为2的文档
DELETE users/_doc/2

# 删除 users 索引
DELETE users
代码语言:javascript
复制
# 创建或修改id为1的文档
PUT users/_doc/1
{
  "firstname": "jack",
  "lastname": "ma"
}

# 创建id为2的文档,如果索引中已经存在相同的id,会报错,创建失败;如果不存在相同的id,则创建成功
PUT users/_create/2
{
  "firstname": "will",
  "lastname": "smith"
}

# 批量查询多个指定index的指定field的值
GET _mget 
{
  "docs" : [
   {"_index": "users", "_id": 1},
   {"_index": "users", "_id": 2}
  ]
}

# 批量插入数据,如果id不存在,则创建;如果id存在,则更新
POST users/_bulk 
{"index" : {"_id" : 3}}
{"firstname": "A", "lastname": "a"}
{"index" : {"_id" : 4}}
{"firstname": "B", "lastname": "b"}
{"index" : {"_id" : 5}}
{"firstname": "C", "lastname": "c"}

URI 查询

代码语言:javascript
复制
# 查询title中包含2012的所有电影
GET movies/_search?q=2012

# 查询title中包含2012的所有电影,df(default field)
GET movies/_search?q=2012&df=title

# 查询title中包含2012的所有电影
GET movies/_search?q=title:2012

分页搜索,from表示偏移量,从0开始,size表示每页显示的数量

代码语言:javascript
复制
# 查询title中包含2012的所有电影,从第10条开始算起(不包含第10条),查询8条数据
GET movies/_search?q=title:2012&from=10&size=8
代码语言:javascript
复制
# 查询title中包含Beautiful或Mind的所有数据
GET movies/_search?q=title:Beautiful Mind
GET movies/_search?q=title:(Beautiful Mind)
GET movies/_search?q=title:(+Beautiful +Mind)

# 查询title中包含"Beautiful Mind"这个短语的所有数据
GET movies/_search?q=title:"Beautiful Mind"

# 查询title中既包含Mind,又包含Beautiful的所有数据
GET movies/_search?q=title:(Mind AND Beautiful)

# 查询title中包含Mind,或包含Beautiful的所有数据
GET movies/_search?q=title:(Mind OR Beautiful)

# 查询title中包含Beautiful但不包含Mind的所有数据
GET movies/_search?q=title:(Beautiful NOT Mind)
GET movies/_search?q=title:(Beautiful -Mind)

# 查询title中包含Beautiful且电影上映时间在2012年之后的所有数据
GET movies/_search?q=title:Beautiful AND year:>=2012

# 查询电影上映时间在2018年之后的所有数据
GET movies/_search?q=year:>=2018

# 注意[空格]格式问题
# 查询在2012到2017年的所有数据
GET movies/_search?q=year:(>=2012 AND <2018)

# 查询2016年到2017年上映的电影,开头可以是 { [,但必须以 ] 结尾
GET movies/_search?q=year:{2015 TO 2017]

# ? 代表一个字母
GET movies/_search?q=title:Min?

# 查询title中包含以Min开头的字母的电影
GET movies/_search?q=title:Min*

Analysis

Analysis(只是一个概念),本文分析是将全文本转换为一系列单词的过程,也叫分词。analysis是通过analyzer(分词器)来实现的,可以使用Elasticsearch内置的分词器,也可以自己去定制一些分词器。

除了在数据写入的时候进行分词处理,在查询的时候也可以使用分析器对查询语句进行分词。

analyzer

analyzer是由三部分组成:

  1. Character Filter:将文本中html标签剔除
  2. Tokenizer:按照规则进行分词,在英文中按照空格分词
  3. Token Filter:去掉 stop、world(停顿词,a、an、the、is、are等),然后转换小写

内置分词器

分词器名称

处理过程

Standard Analyzer

默认的分词器,按词切分,小写处理

Simple Analyzer

按照非字母切分(符号、数字被过滤),小写处理

Stop Analyzer

小写处理,停用词过滤(the, a, this)

Whitespace Analyzer

按照空格切分,不转小写

Keyword Analyzer

不分词,直接将输入当做输出

Pattern Analyzer

正则表达式,默认是\W+(非字符串分隔)

Standard Analyzer

默认的分词器,按词切分,小写处理

代码语言:javascript
复制
GET _analyze
{
  "analyzer": "standard",
  "text": ["2 Running quick brown-foxes leap over lazy dog in the summer evening"]
}

Simple Analyzer

按照非字母切分(符号、数字被过滤),小写处理

代码语言:javascript
复制
GET _analyze
{
  "analyzer": "simple",
  "text": ["2 Running quick brown-foxes leap over lazy dog in the summer evening"]
}

Stop Analyzer

小写处理,停用词过滤(the, a, this)

代码语言:javascript
复制
GET _analyze
{
  "analyzer": "stop",
  "text": ["2 Running quick brown-foxes leap over lazy dog in the summer evening"]
}

Whitespace Analyzer

按照空格切分,不转小写

代码语言:javascript
复制
GET _analyze
{
  "analyzer": "whitespace",
  "text": ["2 Running quick brown-foxes leap over lazy dog in the summer evening"]
}

Keyword Analyzer

不分词,直接将输入当做输出

代码语言:javascript
复制
GET _analyze
{
  "analyzer": "keyword",
  "text": ["2 Running quick brown-foxes leap over lazy dog in the summer evening"]
}

Pattern Analyzer

正则表达式,默认是\W+(非字符串分隔)

代码语言:javascript
复制
GET _analyze
{
  "analyzer": "pattern",
  "text": ["2 Running quick brown-foxes leap over lazy dog in the summer evening"]
}

Request Body 深入搜索

term 查询

term是表达语义的最小单位,在搜索的时候基本都要使用到term。

term查询的种类:Term Query、Range Query等等。

在ES中,term查询不会对输入的内容进行分词处理,而是作为一个整体,在倒排索引中查找准确的词项,并算分。我们也可以使用 Constant Score 将查询转换为一个 filter,避免算分,利用缓存,提高查询的效率

term 与 terms

term 用于查询单个值,terms用于查询多个值

代码语言:javascript
复制
# 查询电影名字中包含有 beautiful 这个单词的所有电影,对于输入的单词不会进行分词的处理。
GET movies/_search
{
  "query": {
    "term": {
      "title": {
        "value": "beautiful"
      }
    }
  }
}
代码语言:javascript
复制
# 查询电影名字中包含有 beautiful 或者 mind 的所有电影,对于输入的单词不会进行分词的处理。
GET movies/_search
{
  "query": {
    "terms": {
      "title": [
        "beautiful",
        "mind"
      ]
    }
  }
}

range

搜索排序,使用sort表示,例如按year字段降序排列;

代码语言:javascript
复制
# 查询上映时间在2016到2018年的所有电影,根据上映时间进行倒序排序
GET movies/_search
{
  "query": {
    "range": {
      "year": {
        "gte": 2016,
        "lte": 2018
      }
    }
  },
  "sort": [
    {
      "year": {
        "order": "desc"
      }
    }
  ]
}

Constant Score

代码语言:javascript
复制
# 查询 title 中包含 beautiful 的所有电影,不进行相关算分,查询数据进行缓存,提高效率
GET movies/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "title": "beautiful"
        }
      }
    }
  }
}

全文查询

全文查询的种类:Match Query、Match Phrase Query、Query String 、Query 等

索引和搜索的时候都会进行分词,在查询的时候,会对输入进行分词,然后每个词项会逐个到底层进行查询,将最终的结果进行合并

match

条件搜索,使用match表示匹配条件,例如搜索出titlebeautiful的文档

代码语言:javascript
复制
# 查询电影名字中包含有 beautiful 的所有数据,每页10条,取第二页数据
GET movies/_search
{
  "query": {
    "match": {
      "title": "beautiful"
    }
  },
  "from": 1,
  "size": 10
}

文本类型字段的条件搜索,例如搜索title字段中包含20的文档,对比上一条搜索可以发现,对于数值类型match操作使用的是精确匹配,对于文本类型使用的是模糊匹配

搜索并返回指定字段内容,使用_source表示,例如只返回titleid两个字段内容

代码语言:javascript
复制
# 查询电影名字中包含有 beautiful 或者 mind 的所有数据,但只显示 title 和 id 这两个属性
GET movies/_search
{
  "_source": ["title", "id"],
  "query": {
    "match": {
      "title": "beautiful mind"
    }
  }
}

match_phrase

短语匹配搜索,使用match_phrase表示,例如搜索title字段中同时包含beautifulmind的文档

代码语言:javascript
复制
# 查询电影名字中包含 beautiful mind 这个短语的所有数据
GET movies/_search
{
  "query": {
    "match_phrase": {
      "title": "beautiful mind"
    }
  }
}

multi_match

代码语言:javascript
复制
# 查询 title 或 genre 中包含有 beautiful 或 Adventure 的所有数据
GET movies/_search
{
  "query": {
    "multi_match": {
      "query": "beautiful Adventure",
      "fields": ["title", "genre"]
    }
  }
}

match_all

代码语言:javascript
复制
# 查询所有数据
GET movies/_search
{
  "query": {
    "match_all": {}
  }
}

query_string

代码语言:javascript
复制
# 查询 title 中包含 beautiful 和 mind 的所有电影
GET movies/_search
{
  "query": {
    "query_string": {
      "default_field": "title",
      "query": "mind AND beautiful"
    }
  }
}


GET movies/_search
{
  "query": {
    "query_string": {
      "default_field": "title",
      "query": "mind beautiful",
      "default_operator": "AND"
    }
  }
}

simple_query_string

simple_query_string覆盖了很多其他查询的用法。

代码语言:javascript
复制
# 查询 title 中包含 beautiful 和 mind 的所有电影
GET movies/_search
{
  "query": {
    "simple_query_string": {
      "query": "beautiful + mind",
      "fields": ["title"]
    }
  }
}


GET movies/_search
{
  "query": {
    "simple_query_string": {
      "query": "beautiful mind",
      "fields": ["title"],
      "default_operator": "AND"
    }
  }
}


# 查询 title 中包含 beautiful mind 这个短语的所有电影(用法类似 match_phrase)
GET movies/_search
{
  "query": {
    "simple_query_string": {
      "query": "\"beautiful mind\"",
      "fields": ["title"]
    }
  }
}


# 查询 title 或 genre 中包含 beautiful 或 mind 的所有电影(用法类似 multi_match)
GET movies/_search
{
  "query": {
    "simple_query_string": {
      "query": "beautiful mind",
      "fields": ["title", "genre"]
    }
  }
}


# 查询 title 中包含 beautiful mind 或者 Modern Romance 这两个短语的所有电影
GET movies/_search
{
  "query": {
    "simple_query_string": {
      "query": "\"beautiful mind\" | \"Modern Romance\"",
      "fields": ["title"]
    }
  }
}


# 查询 title 或者 genre 中包含 beautiful 和 mind 这两个词,或者 Comedy 和 Romance 和 Musical 和 Drama 和 Children 这五个词的所有数据
GET movies/_search
{
  "query": {
    "simple_query_string": {
      "query": "(beautiful + mind) | (Comedy + Romance + Musical + Drama + Children)",
      "fields": ["title", "genre"]
    }
  }
}


# 查询 title 中包含 beautiful 和 people,但不包含 Animals 的所有数据
GET movies/_search
{
  "query": {
    "simple_query_string": {
      "query": "beautiful + people + -Animals",
      "fields": ["title"]
    }
  }
}

模糊搜索

代码语言:javascript
复制
# 查询 title中从第六个字母开始只要最多纠正一次,就与 neverendign 匹配的所有数据
GET movies/_search
{
  "query": {
    "fuzzy": {
      "title": {
        "value": "neverendign",
        "fuzziness": 1,
        "prefix_length": 5
      }
    }
  }
}

组合查询

组合搜索,使用bool来进行组合,must表示同时满足

条件

说明

must

同时满足

should

满足其中任意一个

must_not

同时不满足

filter

过滤搜索

代码语言:javascript
复制
# 查询 title 中包含 beautiful 或 mind 单词,并且上映时间在 2016到2018 年的所有数据
GET movies/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "simple_query_string": {
            "query": "beautiful mind",
            "fields": ["title"]
          }
        },
        {
          "range": {
            "year": {
              "gte": 2016,
              "lte": 2018
            }
          }
        }
      ]
    }
  }
}

搜索过滤,使用filter来表示,例如过滤出year字段在2016-2018的文档

代码语言:javascript
复制
# 查询 title 中包含 beautiful 单词,并且上映年份在 2016到2018 年的所有数据,但不会进行相关行算分
GET movies/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "title": "beautiful"
          }
        },
        {
          "range": {
            "year": {
              "gte": 2016,
              "lte": 2018
            }
          }
        }
      ]
    }
  }
}

Mapping

mapping 类似于数据库中的schema,作用如下:

  • 定义索引中的字段类型;
  • 定义字段的数据类型,例如:布尔、字符串、数字、日期
  • 字段倒排索引的设置

数据类型

类型

描述

Text、Keyword

字符串。Keyword的意思是字符串的内容不会被分词处理。Text类型ES会自动的添加一个Keyword类型的子字段。

Date

日期类型

Integer、Float、Long

数字类型

Boolean

布尔类型

Geo_point、Geo_shape

特殊类型

Mapping的定义

语法

代码语言:javascript
复制
PUT users
{
  "mappings": {
       // mapping信息
  }
}

定义mapping的建议方式: 写入一个样本文档到临时索引中,ES会自动生成mapping信息,通过访问 mapping信息的api查询mapping的定义,修改自动生成的mapping成为我们需要方式,创建索引,删 除临时索引,简而言之就是 “卸磨杀驴” 。

创建Mapping

代码语言:javascript
复制
PUT users
{
  "mappings": {
    "properties": {
      "id": {
        "type": "integer"
      },
      "name": {
        "type": "keyword"
      },
      "job": {
        "type": "keyword"
      },
      "age": {
        "type": "integer"
      },
      "gender": {
        "type": "keyword"
      }
    }
  }
}

填充测试数据

代码语言:javascript
复制
PUT users/_bulk
{"index": {"_id": 1}} 
{"id": 1, "name": "Bob", "job": "java", "age": 21, "sal": 8000, "gender": "female"} 
{"index": {"_id": 2}}
{"id": 2, "name": "Rod", "job": "html", "age": 31, "sal": 18000, "gender": "female"} 
{"index": {"_id": 3}} 
{"id": 3, "name": "Gaving", "job": "java", "age": 24, "sal": 12000, "gender": "male"} 
{"index": {"_id": 4}} 
{"id": 4, "name": "King", "job": "dba", "age": 26, "sal": 15000, "gender": "female"} 
{"index": {"_id": 5}} 
{"id": 5, "name": "Jonhson", "job": "dba", "age": 29, "sal": 16000, "gender": "male"} 
{"index": {"_id": 6}} 
{"id": 6, "name": "Douge", "job": "java", "age": 41, "sal": 20000, "gender": "female"} 
{"index": {"_id": 7}} 
{"id": 7, "name": "cutting", "job": "dba", "age": 27, "sal": 7000, "gender": "male"} 
{"index": {"_id": 8}} 
{"id": 8, "name": "Bona", "job": "html", "age": 22, "sal": 14000, "gender": "female"}
{"index": {"_id": 9}} 
{"id": 9, "name": "Shyon", "job": "dba", "age": 20, "sal": 19000, "gender": "female"} 
{"index": {"_id": 10}} 
{"id": 10, "name": "James", "job": "html", "age": 18, "sal": 22000, "gender": "male"}
{"index": {"_id": 11}} 
{"id": 11, "name": "Golsling", "job": "java", "age": 32, "sal": 23000, "gender": "female"} 
{"index": {"_id": 12}} 
{"id": 12, "name": "Lily", "job": "java", "age": 24, "sal": 2000, "gender": "male"} 
{"index": {"_id": 13}} 
{"id": 13, "name": "Jack", "job": "html", "age": 23, "sal": 3000, "gender": "female"} 
{"index": {"_id": 14}} 
{"id": 14, "name": "Rose", "job": "java", "age": 36, "sal": 6000, "gender": "female"} 
{"index": {"_id": 15}} 
{"id": 15, "name": "Will", "job": "dba", "age": 38, "sal": 4500, "gender": "male"} 
{"index": {"_id": 16}} 
{"id": 16, "name": "smith", "job": "java", "age": 32, "sal": 23000, "gender": "male"}

再谈搜索

聚合查询

对搜索结果进行聚合,使用aggs来表示,类似于MySql中的group by

语法

代码语言:javascript
复制
GET indexName/_search
{
  "aggs": {
    "aggs_name": {  // 名字自定义
      "AGG_TYPE": {
        // aggregation body
      }
    }
  }
}

单值输出

ES中大多数的数学计算只输出一个值,如:min、max、sum、avg、cardinality

代码语言:javascript
复制
# 查询总和工资
GET users/_search
{
  "size": 0, 
  "aggs": {
    "sal_sum": {
      "sum": {
        "field": "sal"
      }
    }
  }
}


# 查询平均工资
GET users/_search
{
  "size": 0,
  "aggs": {
    "avg_sal": {
      "avg": {
        "field": "sal"
      }
    }
  }
}


# 查询总共有多少个岗位,cardinality的值类似于sql中的count distinct,即去重统计总数
GET users/_search
{
  "size": 0,
  "aggs": {
    "count_job": {
      "cardinality": {
        "field": "job"
      }
    }
  }
}

多值输出

ES还有些函数,可以一次性输出很多个统计的数据:terms、stats

代码语言:javascript
复制
# 查询工资的信息(数量、最大、最小、平均、总数)
GET users/_search
{
  "size": 0,
  "aggs": {
    "stats_sal": {
      "stats": {
        "field": "sal"
      }
    }
  }
}


# 查询到达不同城市的航班数量
GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "terms_flight_dest": {
      "terms": {
        "field": "DestCountry"
      }
    }
  }
}


# 查询每个岗位有多少人数
GET users/_search
{
  "size": 0,
  "aggs": {
    "terms_job": {
      "terms": {
        "field": "job"
      }
    }
  }
}


# 查询目的地的航班次数以及天气信息
GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "terms_dest_city": {
      "terms": {
        "field": "DestCityName"
      },
      "aggs": {
        "terms_whether_info": {
          "terms": {
            "field": "DestWeather"
          }
        }
      }
    }
  }
}


# 查询每个岗位下工资的信息(平均、最高、最低)
GET users/_search
{
  "size": 0,
  "aggs": {
    "terms_job_info": {
      "terms": {
        "field": "job"
      },
      "aggs": {
        "stats_sal_info": {
          "stats": {
            "field": "sal"
          }
        }
      }
    }
  }
}


# 查询不同工种的男女数量,然后统计不同工种下男女员工的工资信息
GET users/_search
{
  "size": 0,
  "aggs": {
    "terms_job_info": {
      "terms": {
        "field": "job"
      },
      "aggs": {
        "terms_gender_info": {
          "terms": {
            "field": "gender"
          },
          "aggs": {
            "stats_sal_info": {
              "stats": {
                "field": "sal"
              }
            }
          }
        }
      }
    }
  }
}


# 查询年龄最大的两位员工的信息
GET users/_search
{
  "size": 0,
  "aggs": {
    "top_age_2": {
      "top_hits": {
        "size": 2,
        "sort": [
          {
            "age": {
              "order": "desc"
            }
          }  
        ]
      }
    }
  }
}


# 查询不同区间人员的工资统计信息
GET users/_search
{
  "size": 0,
  "aggs": {
    "range_sal_info": {
      "range": {
        "field": "sal",
        "ranges": [
          {
            "key": "0 <= sal <= 5000", 
            "from": 0,
            "to": 5000
          },
          {
            "key": "5001 <= sal <= 10000",
            "from": 5001,
            "to": 10000
          }
        ]
      }
    }
  }
}


# 以直方图的方式以每5000元为一个区间查看工资信息
## interval:指定的值为一个区间
## extended_bounds:指定区间的范围
GET users/_search
{
  "size": 0,
  "aggs": {
    "histogram_sal_info": {
      "histogram": {
        "field": "sal",
        "interval": 5000,
        "extended_bounds": {
          "min": 0,
          "max": 30000
        }
      }
    }
  }
}


# 查询平均工资中最低工资的工种
GET users/_search
{
  "size": 0,
  "aggs": {
    "job_info": {
      "terms": {
        "field": "job"
      },
      "aggs": {
        "job_avg_sal": {
          "avg": {
            "field": "sal"
          }
        }
      }
    },
    "min_sal_job": {
      "min_bucket": {
        "buckets_path": "job_info>job_avg_sal"
      }
    }
  }
}


# 求工资和工种的信息
GET users/_search
{
  "size": 0,
  "aggs": {
    "job_info": {
      "terms": {
        "field": "job"
      }
    },
    "sal_info": {
      "stats": {
        "field": "sal"
      }
    }
  }
}


# 查询年龄大于30的员工的平均工资
GET users/_search
{
  "size": 0,
  "query": {
    "range": {
      "age": {
        "gte": 30
      }
    }
  },
  "aggs": {
    "avg_sal": {
      "avg": {
        "field": "sal"
      }
    }
  }
}


# 查询Java员工的平均工资
GET users/_search
{
  "size": 0,
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "job": "java"
        }
      },
      "boost": 1.2
    }
  },
  "aggs": {
    "avg_sal": {
      "avg": {
        "field": "sal"
      }
    }
  }
}


# 查询30岁以上的员工的平均工资和所有的工种信息
GET users/_search
{
  "size": 0,
  "aggs": {
    "older_emp": {
      "filter": {
        "range": {
          "age": {
            "gte": 30
          }
        }
      },
      "aggs": {
        "avg_sal": {
          "avg": {
            "field": "sal"
          }
        }
      }
    },
    "job_info": {
      "terms": {
        "field": "job"
      }
    }
  }
}

推荐搜索

在搜索过程中,因为单词的拼写错误,没有得到任何的结果,希望ES能够给我们一个推荐搜索。

代码语言:javascript
复制
GET movies/_search
{
  "suggest": {
    # 自定义的名称
    "title_suggestion": {
      "text": "drema",
      "term": {
        "field": "title",
        "suggest_mode": "popular"
      }
    }
  }
}

suggest_mode

说明

popular

推荐词频更高的一些搜索

missing

当没有要搜索的结果的时候才推荐

always

无论什么情况下都进行推荐

自动补全

自动补全应该是我们在日常的开发过程中最常见的搜索方式了。

自动补全的功能对性能的要求极高,用户每发送输入一个字符就要发送一个请求去查找匹配项。ES采取了不同的数据结构来实现,并不是通过倒排索引来实现的;需要将对于的数据类型设置为completion;所以在将数据索引进ES之前需要先定义mapping信息。

需要重新导入数据,先跳过

高亮显示

高亮显示在实际的应用中也会碰到很多。

代码语言:javascript
复制
GET movies/_search
{
  "query": {
    "match": {
      "title": "beautiful"
    }
  },
  "highlight": {
    "pre_tags": "<span color='red'>",   # 需要高亮文本的前置 html 内容
    "post_tags": "</span>",             # 需要高亮文本的后置 html 内容
    "fields": {                         # 需要高亮的属性
      "title": {}
    }
  }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-03-04|,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Elasticsearch7教程
  • 前序
    • 正排索引和倒排索引
      • 导读
      • 正排索引
      • 倒排索引
  • 下载及配置
    • 下载
      • 解决跨域
        • 中文显示
        • Elasticsearch的基本概念
          • shard(分片)
            • 分片好处
            • 注意事项
          • replica(副本)
            • 副本的重要性
            • 注意事项
          • index(索引)
            • document(文档)
              • type(类型)
                • mapping(映射)
                  • field(字段)
                    • 概念关系图
                    • RestAPI
                      • CRUD 操作
                        • URI 查询
                        • Analysis
                          • analyzer
                            • 内置分词器
                              • Standard Analyzer
                              • Simple Analyzer
                              • Stop Analyzer
                              • Whitespace Analyzer
                              • Keyword Analyzer
                              • Pattern Analyzer
                          • Request Body 深入搜索
                            • term 查询
                              • term 与 terms
                              • range
                              • Constant Score
                            • 全文查询
                              • match
                              • match_phrase
                              • multi_match
                              • match_all
                              • query_string
                              • simple_query_string
                            • 模糊搜索
                              • 组合查询
                              • Mapping
                                • 数据类型
                                  • Mapping的定义
                                    • 语法
                                  • 创建Mapping
                                    • 填充测试数据
                                • 再谈搜索
                                  • 聚合查询
                                    • 语法
                                    • 单值输出
                                    • 多值输出
                                  • 推荐搜索
                                    • suggest_mode
                                  • 自动补全
                                    • 高亮显示
                                    相关产品与服务
                                    Elasticsearch Service
                                    腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
                                    领券
                                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档