本文非彻底直译译文,主要参考的的是 elasticsearch 6.5 版的官网文档 Getting Started,能够把这篇文章理解为我的学习笔记,我力求详略得当吧。node
文末会附上 Getting Started 阅读梳理的思惟导图。linux
为了能更加轻松地进入 elasticsearch 的世界,本文将先从基础角度给介绍了 es 的使用。git
Elasticsearch 是一款开源的全文搜索与分析引擎,它拥有高扩展、大容量数据的存储和处理特性,有着近乎实时的处理效果。elasticsearch 的使用场景仍是比较多的,好比 APP 的搜索服务、ELK 实现日志收集与分析、BI 商业智能等。github
本文会逐步引导你们进入 elasticsearch 的世界,初步窥探它的使用。相关内容涉及以下:sql
总体上的内容仍是比较多的。数据库
Elasticsearch 中有一些基础但很核心的概念须要咱们提早了解,它们对咱们的学习将起到很大帮助。json
具体是哪些概念呢?windows
下面咱们将逐一介绍。bash
什么是近实时?
它表示一个文档从被索引(存储使文档可搜索)到真正能被搜索之间有一个短暂的延迟,而非实时,这个延迟默认是 1 秒。固然,默认延迟能够修改的。
集群是节点的集合。
集群实现了在多节点上进行大容量数据存储和搜索的能力。每一个集群都拥有惟一名称,而节点正是根据集群的名称决定是否加入某个集群。不一样环境的集群的名称不能相同,如开发、测试、线上三套环境,集群可分别命名为 logging-dev、logging-test、logging-prod。
节点,集群组成的一部分,负责具体的事务处理,好比数据存储、文档索引、搜索执行等。节点也有惟一个名称,若是没有指定将随机生成。
节点可经过配置集群名称,指定加入哪一个集群,节点默认的集群名称是 elasticsearch。若是咱们在一个网络环境下启动多个节点,而且它们之间能够相互发现,就将会自动组织一个名称为 elasticsearch 的集群。
索引是一系列类似文档的集合,例如,咱们把客户信息存放到一个索引,订单信息存储到另外一个索引中。索引可经过名称识别,名称必须小写。当操做文档时,咱们须要经过索引名称指定。
索引的数量,集群中并无限制定义索引的数量。
elasticsearch 6.0 已丢弃功能,不具体介绍了。
有一点须要注意,为与老版本兼容,该功能暂未完全移除,当前一个索引仍可设置类型,但当前只能指定一个类型。通常状况下,咱们设置一个固定 type 便可,好比 _doc。
被索引的基础信息单元,好比一个客户、一件产品、或是一笔订单。文档可用 JSON 形式表示,它是一种很是广泛的数据交换格式。索引中,咱们能够存听任意数量的文档。
分片和副本是 elasticsearch 很是核心的概念。
咱们知道,elasticsearch 存储的数据量能突破单个硬件的限制,数据处理速度有着近实时的水平。这些都和分片和副本有着很大关系。
分片实现了索引文档分散分布,而且每一个切片都是功能完善的,索引是独立的,可能分布在集群中的任意节点。分片的重要性主要体如今使 elasticsearch 存储容量的水平扩展和分布式并行处理都成为了现实。
副本提升了 elasticsearch 的容错能力。网络环境下,异常随时可能发生,好比一些节点或分片从网络中消失。一旦设置了副本,索引就会同时拥有主分片和副本分片。一旦某个分片发生异常,还有其余分片可替代。并且,副本也能够提升请求的处理速度,一个分片上的副本可同时并行处理多个请求。
一句话简述,每一个索引能够由多个分片组成,而每一个分片也能够拥有多个副本。
介绍完了核心概念,是否已经开始蠢蠢欲动了?开始安装本身的集群吧。
本节主要介绍 elasticsearch 的安装。另外,因为要使用 kibana 的 devtools 控制台,将也会介绍下 kibana 的安装。
首先安装依赖,elasticsearch 是 Java 开发,6.5 版依赖 Java 8,建议安装 Oracle JDK 1.8.0_131。Java 安装完成后,就能够开始安装 elasticsearch 了。
简单起见,咱们只介绍二进制包的安装。
安装过程仅仅三步搞定!
$ curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.5.4.tar.gz
$ tar -xvf elasticsearch-6.5.4.tar.gz
$ cd elasticsearch-6.5.4/bin
$ ./elasticsearch -d # -d 表示后台启动
复制代码
安装启动完成后,可经过访问 localhost:9200 确认下实例运行是否正常。
若是想了解 Mac 的 homebrew 安装或 windows 下的 MSI Installer Package 安装,可自行阅读官方文档。
Kibana 的安装与 elasticsearch 的不一样,须要区别不一样的平台系统。本节将介绍 Mac 与 Linux 下的安装,它们均可以经过下载对应系统的 tar 包完成。
Linux 系统,咱们以 Linux x86_64 为例。安装命令以下:
$ wget https://artifacts.elastic.co/downloads/kibana/kibana-6.5.4-linux-x86_64.tar.gz
$ shasum -a 512 kibana-6.5.4-linux-x86_64.tar.gz
$ tar -xzf kibana-6.5.4-linux-x86_64.tar.gz
$ cd kibana-6.5.4-linux-x86_64/
$ ./bin/kibana
复制代码
MacOS 系统,安装命令以下:
$ curl -O https://artifacts.elastic.co/downloads/kibana/kibana-6.5.4-darwin-x86_64.tar.gz
$ shasum -a 512 kibana-6.5.4-darwin-x86_64.tar.gz
$ tar -xzf kibana-6.5.4-darwin-x86_64.tar.gz
$ cd kibana-6.5.4-darwin-x86_64/
$ ./bin/kibana
复制代码
若是但愿 kibana 在后台运行,能够经过 nohup 实现。完成后,访问 localhost:5601 下确认状态,它会默认链接本地启动的 elasticsearch 集群。
好吧!我仍是不想介绍 Windows 下的安装。
若是但愿启动一个多节点集群,咱们能够修改下启动命令,在本地同时启动两个节点,集群名称相同状况下,它们将会自动组织成一个新的集群。命令以下:
$ ./bin/elasticsearch -Ecluster.name=cluster_dev -Epath.data=cluster_node01 -Enode.name=node01 -Ehttp.port=9200 -d
$ ./bin/elasticsearch -Ecluster.name=cluster_dev -Epath.data=cluster_node02 -Enode.name=node02 -Ehttp.port=9201 -d
复制代码
启动成功后,能够进入 kibana 的 devtool 执行 _cat/nodes?v,输出以下:
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
127.0.0.1 29 75 6 3.31 mdi - node01
127.0.0.1 33 75 6 3.31 mdi * node02
复制代码
咱们将会看到集群中已经有了两个节点。
经历了前面几步,elasticsearch 集群已经安装完成,但咱们要如何与它交流呢?其实,elasticsearch 已经提供了一套全面且功能强大的 REST API,用于与集群交互。REST API 涉及功能包括:
本节咱们将简单介绍上面提到的部分 API。
健康检查可让咱们了解集群当前状态,可经过 _cat API 实现。
示例以下:
GET /_cat/health?v
复制代码
输出结果:
epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1565884060 23:47:40 cluster_dev green 2 2 22 21 0 0 0 0 - 100.0%
复制代码
输出结果显示,集群名称为 cluster_dev,状态是 green,当前集群有 2 个节点。
先重点讲讲 green 究竟表明什么意思?
首先,green 表示的是集群的状态,对应字段名称是 status,共有三种状态,分别是 green、yellow 和 red。
当集群状态是 red 时,仍然能够接收处理搜索请求,但咱们须要马上修复它。
经过 _cat/nodes,能够列出当前集群下的全部节点,前面在启动一个多节点集群时,咱们已通过了使用该 API,很少介绍了。
_cat/indices?v 能列出集群中的全部索引。说明一下,indices 是 index 的复数形式。
GET _cat/indices
复制代码
输出以下:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open us_tweet WXkAeMEvR0eukVOFOM1q3w 5 0 6 0 15.7kb 15.7kb
green open gb_user pbOu0n0XQ96mouQ642eutQ 5 0 1 0 5.7kb 5.7kb
green open us_user idxuhX0LQlekzfbjd6kB5w 5 0 1 0 5.7kb 5.7kb
green open gb_tweet SJTleUerT5CaO9Sl-JwIQg 5 0 6 0 15.7kb 15.7kb
复制代码
个人本地集群常常拿来测试,因此这里会看到已经有不少 index,对于你刚搭建好的集群,输出确定就是空的。
接下来,咱们学习下如何建立索引,直接看示例吧。尝试建立一个名为 "customer" 的索引,以下:
PUT customer?pretty
复制代码
PUT 加上索引名称便可。 customer 索引成功建立后,查看下集群当前索引列表,以下:
GET _cat/indices
复制代码
输出结果以下:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
...
green open customer 71RYoldbQ6uXMo56t4bSog 5 1 0 0 1.1kb 460b
...
复制代码
customer 成功建立,包含 5 个主分片和 1 个副本分片,索引中当前的文档数量为 0,索引状态为 green。
索引的状态和集群同样,也是 green、yellow 和 red 这 3 个值,而且含义与集群状态相似。green 是全功能正常,yellow 表示副本未彻底分配,red 表示部分主分片不可用。咱们能够测试一下,中止集群中的一个节点,这时 customer 的状态将会立刻切换为 yellow 状态。
在 elasticsearch 中,"索引" 这个名词经常会搞晕咱们。通常讲到索引,主要是指它的名词含义,好比咱们说,建立一个 customer 索引。但有时,它又是动词,好比咱们在增长和更新文档时,常会说索引一个文档,在这种状况下,能够把它理解为存储文档并使其可搜索。
那如何索引一个文档呢?好比,索引一个 ID 为 1 的 customer 文档到 customer 索引中,以下。
PUT /customer/_doc/1?pretty
{
"name": "John Doe"
}
复制代码
响应返回:
{
"_index" : "customer",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
复制代码
结果代表,咱们已经成功建立一个 ID 为 1 的文档。从这里也能看出,在索引一个文档以前,并不要求咱们明确建立索引 customer,若是 customer 索引不存在,elasticsearch 将会自动帮助咱们建立索引。
检索刚才索引的文档。
GET /customer/_doc/1?pretty
复制代码
响应以下:
{
"_index" : "customer",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : { "name": "John Doe" }
}
复制代码
found 字段代表,咱们已经成功检索到了一个 ID 为 1 的文档。_source 中的内容是检索文档的完整内容。
让咱们删除掉刚刚建立的索引。
DELETE /customer?pretty
复制代码
如此,咱们就成功删除了以前建立的 customer。若是不肯定,可使用 GET _cat/indices 检查下。
回顾下前面介绍的那些 API,咱们从新再走一遍。
PUT /customer
PUT /customer/_doc/1
{
"name": "John Doe"
}
GET /customer/_doc/1
DELETE /customer
复制代码
仔细观察上面的命令,你可能会发现一个比较通用的模式,以下:
<HTTP Verb> /<Index>/<Type>/<ID>
复制代码
这个模式在 elasticsearch 中很是广泛,记住它,这将对 elasticsearch 学习之旅将会很是有帮助。
区别于传统关系型数据库的实时性特色,elasticsearch 是近实时的,也就是说,在文档被 create/update/delete 与搜索结果中出现之间将会有 1 秒的延迟。
建立和替换文档本质上都属于索引文档,于是,咱们以前用来建立文档的命令一样适用于文档替换。
由于 customer 索引重建过,咱们从新建立一个 ID 为 1 的文档。以下:
PUT /customer/_doc/1?pretty
{
"name": "John Doe"
}
复制代码
一样的命令便可实现文档更新,咱们只须要传递不一样的文档内容便可,以下:
PUT /customer/_doc/1?pretty
{
"name": "Jane Doe"
}
复制代码
将 ID 为 1 的文档中 name 由 Johh Doe 更新为 Jane Doe。若是指定 ID 文档不存在,将会建立新的文档,不然更新当前文档。
好比,ID 为 2 的文档不存在,经过以下命令建立。
PUT /customer/_doc/2?pretty
{
"name": "Jane Doe"
}
复制代码
索引文档时,ID 不是必须的,若是不指定,elasticsearch 会自动为这个文档指定一个随机的 ID,并做为响应的一部分返回给你。
示例以下:
POST /customer/_doc?pretty
{
"name": "Jane Doe"
}
复制代码
这种状况下,咱们须要使用 POST 代替 PUT 提交请求。
响应结果:
{
"_index": "customer",
"_type": "_doc",
"_id": "Z-RnpGwBe6KTDC6t3MGV",
"_version": 1,
"result": "created",
"_shards": {
"total": 1,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}
复制代码
上面能够看到 elasticsearch 为咱们生成的文档 ID,Z-RnpGwBe6KTDC6t3MGV。
说完文档的索引和替换,咱们再来谈谈文档的更新。提早说明,elasticsearch 并不是真的去更新文档,它的更新操做与替换相似,包含删除旧文档和索引新文档两个操做。
示例演示,更新前面建立的 ID 为 1 的文档,更新 name 字段为 Jane Doe。
POST /customer/_doc/1/_update?pretty
{
"doc": { "name": "Jane Doe" }
}
复制代码
示例 2,更新 name 为 Jane Doe 的同时,增长一个字段 age。
POST /customer/_doc/1/_update?pretty
{
"doc": { "name": "Jane Doe", "age": 20 }
}
复制代码
示例 3,使用脚本更新文档,好比将 ID 为 1 的文档的字段 age 加 5。
POST /customer/_doc/1/_update?pretty
{
"script": "ctx._source.age += 5"
}
复制代码
上面的例子,ctx._source 表示的是咱们将要更新的文档。这里是经过指定 ID 的方式查询要更新的文档,elasticsearch 也能够像 SQL 同样,经过复杂查询实现更新。
删除文档最简单直接,HTTP 方法换成 DELETE,指定文档 ID 便可。以下:
DELETE /customer/_doc/2?pretty
复制代码
和更新相似,删除也能够根据查询结果执行删除,API 是 _delete_by_query。若是是删除索引中的全部文档,直接删除索引更直接点。
通过前面的学习,咱们已经了解了 elasticsearch 一些基础 API 的使用,如文档的索引、更新、删除。这一小节介绍一个新的 API,_bulk API,它支持将多个操做打包成一个请求,实现批处理。这样能够更加高效的执行操做,也能减小网络传递次数。
一个快速入门案例,以下:
POST /customer/_doc/_bulk?pretty
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }
复制代码
索引了 2 个文档,一个文档 ID 1,name 为 John Doe,另外一个文档 ID 2,name 为 Jane Doe。
再看一个案例,以下:
POST /customer/_doc/_bulk?pretty
{"update":{"_id":"1"}}
{"doc": { "name": "John Doe becomes Jane Doe" } }
{"delete":{"_id":"2"}}
复制代码
批处理包含 2 个操做,更新 ID 为 1 文档的 name 字段和删除 ID 为 2 的文档。
批处理中的一个操做失败并不会致使整个 bulk API 处理失败,若是一个操做失败,剩下来的其余操做仍会继续执行。bulk API 处理完成后,响应结果中会包含每一个操做的处理结果。
本节内容主要涉及两个方面:搜索与分析。
搜索分析不可缺乏数据,咱们将使用 elastic 官方提供的数据样本,相对而言,应该比本身的生成更符合真实场景。
一个文档,示例以下:
{
"account_number": 0,
"balance": 16623,
"firstname": "Bradshaw",
"lastname": "Mckenzie",
"age": 29,
"gender": "F",
"address": "244 Columbus Place",
"employer": "Euron",
"email": "bradshawmckenzie@euron.com",
"city": "Hobucken",
"state": "CO"
}
复制代码
官方的数据是用工具随机生成的,工具地址。有兴趣,能够设置本身的数据生成规则。
开始数据加载以前,要先下载数据,下载地址。
$ wget https://raw.githubusercontent.com/elastic/elasticsearch/master/docs/src/test/resources/accounts.json
复制代码
下载完成后,执行以下命令加载数据:
$ curl -H "Content-Type: application/json" -XPOST "localhost:9200/bank/_doc/_bulk?pretty&refresh" --data-binary "@accounts.json"
复制代码
查看索引信息
$ curl "localhost:9200/_cat/indices?v"
复制代码
响应以下:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open bank FFcSux-ETmmUlMJNBCEyqA 5 1 1000 0 957kb 482.3kb
复制代码
能够看出,咱们已经为 bank 成功索引了 1000 个文档。
开始尝试一些简单的搜索。有两种基本的搜索方式:
相对而言,Request Body 方式更灵活,包含了所有的搜索支持。而 URI Search 主要在测试时使用,比较方便。
搜索请求经过 _search 执行。一个示例,经过搜索返回 bank 索引中的全部文档。
GET /bank/_search?q=*&sort=account_number:asc&pretty
复制代码
URI Search 方式实现搜索,经过 q=* 执行匹配所有文档,sort=account_number:asc 指定排序方式。
响应以下:
{
"took" : 63,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1000,
"max_score" : null,
"hits" : [ {
"_index" : "bank",
"_type" : "_doc",
"_id" : "0",
"sort": [0],
"_score" : null,
"_source" : {"account_number":0,"balance":16623,"firstname":"Bradshaw","lastname":"Mckenzie","age":29,"gender":"F","address":"244 Columbus Place","employer":"Euron","email":"bradshawmckenzie@euron.com","city":"Hobucken","state":"CO"}
}, ...
]
}
}
复制代码
结果中的各个参数函数以下:
经过 Reuqest Body 方式执行与上面相同的操做,以下:
GET /bank/_search
{
"query": { "match_all": {} },
"sort": [
{ "account_number": "asc" }
]
}
复制代码
咱们下面主要介绍 Request Body 的使用,毕竟它更增强大。
DSL,全称 Domain Special Language, 即特定领域语言,elasticsearch 制定了一套 JSON 风格的 DSL 语言。它支持的功能很是全面,刚学习它时,会让咱们产生一种恐惧,由于它真的很难。咱们能够先从一些简单的例子看起。
查询全部文档,以下:
GET /bank/_search
{
"query": { "match_all": {} }
}
复制代码
解剖下请求体。query 定义查询语句,match_all 就是咱们将会执行的查询语句,表示匹配索引中的全部文档。
执行上面的查询语句默认只会返回 10 条文档,咱们能够经过指定 size 参数改变默认获取文档数量。以下:
GET /bank/_search
{
"query": { "match_all": {} },
"size": 1
}
复制代码
经过 from 和 size 能够实现分页效果,以下:
GET /bank/_search
{
"query": { "match_all": {} },
"from": 10,
"size": 10
}
复制代码
from 用于指定文档偏移的开始位置,至关于 SQL 中的 offset。
文档默认根据搜索相关度得分排序,不过咱们这里是默认匹配所有,因此文档的相关度得分都是1。除了相关度排序,还能够按其余字段,好比 balance 字段。以下:
GET /bank/_search
{
"query": { "match_all": {} },
"sort": { "balance": { "order": "desc" } }
}
复制代码
继续看下搜索返回文档字段,默认状况下,搜索将会返回文档的全部字段内容。咱们可经过 _source 指定只返回部份内容。
GET /bank/_search
{
"query": { "match_all": {} },
"_source": ["account_number", "balance"]
}
复制代码
如此,搜索将只返回 account_number
和 balance
两个字段。 了解的 SQL 的朋友能够将其与 SELECT 指定列类比。
继续看查询部分吧!
前面,经过 match_all 查询匹配了所有文档。如今,咱们再引入一个新的查询语句,match,它是基于一个字段的查询。
查询 account_number 为 20 的文档。示例以下:
GET /bank/_search
{
"query": { "match": { "account_number": 20 } }
}
复制代码
查询 address 包含 mill 的文档。示例以下:
GET /bank/_search
{
"query": { "match": { "address": "mill" } }
}
复制代码
查询 address 包含 mill 或 lane 的文档。示例以下:
GET /bank/_search
{
"query": { "match": { "address": "mill lane" } }
}
复制代码
match 基于分词查询,2 个查询单词是 or 的关系。若是咱们就要搜索 "mill lane" 呢? 这时可使用 match_pharse。示例以下:
查询 address 包含 "mill lane" 的文档。示例以下:
GET /bank/_search
{
"query": { "match_phrase": { "address": "mill lane" } }
}
复制代码
继续介绍 bool 查询,它容许咱们将上面这些基础查询组合造成一个复合查询。好比,查询同时包含 "mill" 和 "jane" 的文档。
示例以下:
GET /bank/_search
{
"query": {
"bool": {
"must": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}
复制代码
例子中的 bool must 表示文档必须同时知足两个 must 条件。若是是只要知足一个条件便可,咱们可使用 bool should,示例以下:
GET /bank/_search
{
"query": {
"bool": {
"should": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}
复制代码
若是要求二者必须不知足,咱们可使用 bool must_not,示例以下:
GET /bank/_search
{
"query": {
"bool": {
"must_not": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}
复制代码
bool 查询中还能够将上面的这几种查询同时组合起来,同时包含 must、must_not 和 should。
示例以下:
GET /bank/_search
{
"query": {
"bool": {
"must": [
{ "match": { "age": "40" } }
],
"must_not": [
{ "match": { "state": "ID" } }
]
}
}
}
复制代码
注意一点,若是是 must、must_not 和 should 组合时,should 就缺乏了必须知足一个才算匹配的限制,这时,咱们能够经过 minimum_should_match 指定 should 匹配个数。
更复杂的,bool 查询中还能够包含其余的 bool 查询。这里先不介绍了。
谈到过滤以前,咱们就不得不提文档相关度评分,相关度评分是用于衡量搜索语句与文档的匹配程度的一个指标。前面已经提过的查询语句都会参与到这个指标的计算。
但有时,查询仅仅是为了过滤一些不知足条件的文档,咱们并不但愿它们也参与到相关度评分的计算中,由此,咱们并引入了 filter。
前面介绍的 bool 查询中便支持 filter 功能。它能够在不影响相关度评分的状况下,实现文档过滤。以下:
GET /bank/_search
{
"query": {
"bool": {
"must": { "match_all": {} },
"filter": {
"range": {
"balance": {
"gte": 20000,
"lte": 30000
}
}
}
}
}
}
复制代码
bool 查询中包含了 must 和 filter 两部分。filter 部分经过 range query 实现只查询 blanace 知足指定区间的文档,must 中的 match_all 实现所有文档返回。
除了上面介绍的查询,如 match_all、match、bool、range,elasticsearch 还有不少其它查询可用,这里不详细介绍了。只要掌握了前面的知识,咱们已经彻底能够照猫画虎。
利用 elasticsearch 的聚合能力,咱们能够实现分组统计,能够和 SQL 的 GROUP BY 分组和聚合函数类比。搜索和聚合都是经过 _search 请求实现,同一个请求可同时处理搜索与聚合的请求。这样也能够帮助咱们节省必要的网络带宽。
一个例子,按银行卡帐号状态(即 state)分组。默认是返回 top 10。以下:
GET bank/_search
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "state.keyword"
}
}
}
}
复制代码
如何 SQL 呢?以下:
SELECT state, COUNT(*) FROM bank GROUP BY state ORDER BY COUNT(*) DESC LIMIT 10;
复制代码
响应以下:
{
"took": 29,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped" : 0,
"failed": 0
},
"hits" : {
"total" : 1000,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"group_by_state" : {
"doc_count_error_upper_bound": 20,
"sum_other_doc_count": 770,
"buckets" : [ {
"key" : "ID",
"doc_count" : 27
}, {
"key" : "TX",
"doc_count" : 27
}, {
"key" : "AL",
"doc_count" : 25
}, {
"key" : "MD",
"doc_count" : 25
}, {
"key" : "TN",
"doc_count" : 23
}, {
"key" : "MA",
"doc_count" : 21
}, {
"key" : "NC",
"doc_count" : 21
}, {
"key" : "ND",
"doc_count" : 21
}, {
"key" : "ME",
"doc_count" : 20
}, {
"key" : "MO",
"doc_count" : 20
} ]
}
}
}
复制代码
从上面能够看出,ID 为 Idaho 的数量为 27,紧接着是 TX 数量 27,而后是 AL 共 25 个。上面设置 size 为 0,是为隐藏搜索结果内容,仅仅显示聚合结果。
咱们能够在前面的聚合结果的基础上,计算 top 10 的帐户余额平均值。以下:
GET /bank/_search
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "state.keyword",
"order": {
"average_balance": "desc"
}
},
"aggs": {
"average_balance": {
"avg": {
"field": "balance"
}
}
}
}
}
}
复制代码
在 group_by_state 中加入子聚合 average_balance,同时在 group_by_state 中,经过 order 配置实现了按 balance 平均值大小排序的需求。
下面这个例子演示了如何按年龄区间分组,好比 20-2九、30-39 和 40-49,并在基础上,继续按性别分组。最后,计算各个分组 balance 的平均值。
GET /bank/_search
{
"size": 0,
"aggs": {
"group_by_age": {
"range": {
"field": "age",
"ranges": [
{
"from": 20,
"to": 30
},
{
"from": 30,
"to": 40
},
{
"from": 40,
"to": 50
}
]
},
"aggs": {
"group_by_gender": {
"terms": {
"field": "gender.keyword"
},
"aggs": {
"average_balance": {
"avg": {
"field": "balance"
}
}
}
}
}
}
}
}
复制代码
例子中有两个分组 group_by_age 和 group_by_gener 以及一个聚合计算 average_balance。
总的来讲,上面的例子仍是比较循环渐进的。但主要仍是集中在使用层面,并无太多细节的介绍。若是想了解更多与聚合相关的内容,可自行查询官方文档。
Elasticsearch 能够说是一款即简单又复杂的产品。本文只是简单介绍了它的一些基础,并初步体验了下它的使用。到此,仅仅算是开启了一扇门,elasticsearch 的使用远没有那么简单。
再接再砺吧!朋友!