前言

经过前两篇文章得实践,我们已经了解了ElasticSearch的基础知识,本篇文章让我来操作一些更真实的数据集。
我们可以利用www.json-generator.com/生成如下的文档结构:

  {
"account_number": 1,
"balance": 39225,
"firstname": "Amber",
"lastname": "Duke",
"age": 32,
"gender": "M",
"address": "880 Holmes Lane",
"employer": "Pyrami",
"email": "amberduke@pyrami.com",
"city": "Brogan",
"state": "IL"
}

加载简单数据集

我们可以下载es提供的数据集accounts.json,然后推送到ES集群

wget https://github.com/elastic/elasticsearch/blob/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"

我们可以看到1000个文档已经索引到bank索引下了。

[root@XXXXX cusD]# curl "localhost:9200/_cat/indices?v"
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
yellow open index 3BGZ895tTNa8qtM_nA3YmA 5 1 1 0 4.4kb 4.4kb
green open .kibana qCbYeswVT2WCogz_E9Y3Ag 1 0 2 0 13.7kb 13.7kb
yellow open customer x57uWBR3Rg-w2_Dz7Djduw 5 1 1 0 4.5kb 4.5kb
yellow open customerb 80DoY8e3RtinVNV4VGU4Cg 5 1 1 0 4.5kb 4.5kb
yellow open best3 DPh-_bOLQBimS9jqWVyyjw 5 1 3 0 10.9kb 10.9kb
yellow open best1 oD5uUlCbSnqevbRfLvl2Iw 5 1 1 0 5.5kb 5.5kb
yellow open customer2 VyIXSBK6R9yHNYNDlsni3A 5 1 0 0 1.2kb 1.2kb
yellow open customerc Nbglz5hbRO28jyt_XyPNTA 5 1 1 0 4.5kb 4.5kb
yellow open cust xuYth97RShixNtgNpbyxBA 5 1 1 0 4.4kb 4.4kb
yellow open customerf osKgtSLxTPKblJW7mrmO0Q 5 1 1 0 5.1kb 5.1kb
yellow open bank Wrk49iM6TjGItiZKWdnzJA 5 1 1000 0 474.7kb 474.7kb
yellow open customer3 101ZzeNmRuCn9d_NOx5oZg 5 1 0 0 1.2kb 1.2kb
yellow open customere p2BWLci9Qz-1VnOh0vSSQA 5 1 2 0 7.6kb 7.6kb

搜索API

让我们开始运行一些简单的搜索api,有两种方式:

GET /bank/_search?q=*&sort=account_number:asc&pretty

让我们分析下这个搜索请求。我们正在用_search搜索 bank索引。q=代表Es会匹配索引内的全部文档。sort=account_number:asc代表每个文档的字段以account_number升序对结果进行排序。pretty*代表结果以漂亮的json格式输出。
这里摘选部分结果

{
"took": 53,
"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",
"_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"
},
"sort": [
0
]
},
}
  • took - Elasticsearch执行搜索的时间(以毫秒为单位)
  • timed_out - 告诉我们搜索是否超时
  • _shards - 告诉我们搜索了多少个分片,以及搜索成功/失败分片的计数
  • hits - 搜索结果
  • hits.total - 符合我们搜索条件的文档总数
  • hits.hits - 实际的搜索结果数组(默认为前10个文档)
  • hits.sort - 对结果进行排序(如果按分数排序则丢失)
  • hits._score并max_score- 暂时忽略这些字段
    也可以用Request Body方式执行搜索,格式如下:
GET /bank/_search
{
"query": { "match_all": {} },
"sort": [
{ "account_number": "asc" }
]
}

介绍查询语言【Query Language】

Elasticsearch提供了一种JSON样式的特定于域的语言,可用于执行查询。这被称为查询DSL。查询语言非常全面,乍一看可能令人生畏,但实际学习它的最佳方法是从一些基本示例开始。
回到上面的例子,我们执行查询:

GET /bank/_search
{
"query": { "match_all": {} }
}

解析上面的内容,该query部分告诉我们查询定义是什么,match_all部分只是我们想要运行的查询类型。该match_all查询仅仅是在指定索引的所有文件进行搜索。
除了query参数,我们还可以传递其他参数来影响搜索结果。在上面我们传入的部分的示例中 sort,我们传入size:

 GET /bank/_search
{
"query": { "match_all": {} },
"size": 1
}

请注意,如果size未指定,则默认为10。
此示例执行一个 match_all并返回文档10到19:

 GET /bank/_search
{
"query": { "match_all": {} },
"from": 10,
"size": 10
}

from规定文档开始的索引,size指定了查询文档的大小。在实现分页时,这两个参数非常有用。from如果不传,默认为0。

下面的示例执行一个 match_all并按帐户余额降序对结果进行排序,返回前10个(默认大小)文档。

GET /bank/_search
{
"query": { "match_all": {} },
"sort": { "balance": { "order": "desc" } }
}

执行搜索

上面我们已经看到了一些基本的查询示例,让我们再深入了解下QueryDSL。让我们来看下返回的json文档的字段。默认情况下会返回命中文档的所有字段。这被称为源(_source代表命中的字段)。有些情况下,我们只需要部分字段,如下:

 GET /bank/_search
{
"query": { "match_all": {} },
"_source": ["account_number", "balance"]
}

下面我们来说说查询部分。之前我们讲过match_all是匹配所有文档,现在让我们了解一个match query,它能针对特定字段或字段集进行搜索。
下面这个示例能搜索account_number为20的数据:

 GET /bank/_search
{
"query": { "match": { "account_number": 20 } }
}

此示例返回地址中包含术语“mill”或“lane”的所有帐户,这里格外注意【空格隔开的两个单词是or查询】:

GET /bank/_search
{
"query": { "match": { "address": "mill lane" } }
}

此示例演示地址种包含“mill lane”的所有账户,【用match_phrase查询时,空格隔开的依然是一个单词】

GET /bank/_search
{
"query": { "match_phrase": { "address": "mill lane" } }
}

然后我们继续介绍下 bool query,它允许我们使用布尔查询将更小的查询组合成更大的查询。
must 同时满足条件此示例组成两个match查询并返回地址中包含“mill”和“lane”的所有帐户:

GET /bank/_search
{
"query": {
"bool": {
"must": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}

在上面的示例中,该bool must子句指定必须为true才能将文档视为匹配的所有查询。

should或满足一个即可 此示例组成两个match查询并返回地址中包含“mill”或“lane”的所有帐户:

GET /bank/_search
{
"query": {
"bool": {
"should": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}

在上面的示例中,该bool should子句指定了一个查询列表,其中任何一个查询都必须为true,才能将文档视为匹配项。

must_not都不包含 此示例组成两个match查询并返回地址中既不包含“mill”也不包含“lane”的所有帐户:

GET /bank/_search
{
"query": {
"bool": {
"must_not": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}

我们可以在查询中同时组合must,should和must_not子句bool。此外,我们可以bool在任何这些bool子句中组合查询来模仿任何复杂的多级布尔逻辑。
此示例返回任何40岁但不住在ID(aho)的人的所有帐户

GET /bank/_search
{
"query": {
"bool": {
"must": [
{ "match": { "age": "40" } }
],
"must_not": [
{ "match": { "state": "ID" } }
]
}
}
}

执行过滤器

上面的示例中,我们跳过了一个称为文档分数的小细节(_score搜索结果中的字段)。分数是一个数值,它是文档与我们指定的搜索查询匹配程度的相对度量。分数越高,文档越相关,分数越低,文档的相关性越低。
但是查询并不总是需要产生分数,特别是当它们仅用于“过滤”文档集时。Elasticsearch会检测这些情况并自动优化查询执行,以便不计算无用的分数。

我们在上面示例介绍的bool查询还支持filter允许使用查询来限制将与其他子句匹配的文档的子句,而不会更改计算得分的方式。作为示例,让我们介绍一下range查询,它允许我们按一系列值过滤文档。一般数字或日期会用到range。
此示例使用bool查询返回余额大于或等于20000且小于或等于30000的帐户。

GET /bank/_search
{
"query": {
"bool": {
"must": { "match_all": {} },
"filter": {
"range": {
"balance": {
"gte": 20000,
"lte": 30000
}
}
}
}
}
}

解析上面的内容,bool查询包含match_all查询(查询部分)和range查询(过滤部分)。我们可以将任何其他查询替换为查询和过滤器部分。
除了match_all,match,bool,和range查询,有很多可用的其他查询类型的,这里暂时不讲了,我们了解了大致的工作原理后,将这些知识应用于学习和试验其他查询类型应该不会太困难。

执行聚合

聚合提供了从数据中分组和提取统计信息的功能。考虑聚合的最简单方法是将其大致等同于SQL GROUP BY和SQL聚合函数。在Elasticsearch中,您可以执行返回匹配的搜索,同时在一个响应中返回与命中相关的聚合结果。这是非常强大和高效的,因为您可以运行查询和多个聚合,并一次性获取两个(或任一)操作的结果,避免使用简洁和简化的API进行网络往返。
首先,此示例按state对所有帐户进行分组,然后返回按计数降序排序的前10个(默认)states(也是默认值),(这里的group_by_state可理解成自定义的聚合名称,可以自定义改变):

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": 0,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1000,
"max_score": 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
}
]
}
}
}

我们可以看到key为ID的有27个账户,TX也是27个账户,AL的是25个账户,以此类推。
请注意,我们设置size=0为不显示搜索匹配,因为我们只希望在响应中看到聚合结果。
在前一个聚合的基础上,此示例按州计算平均帐户余额(同样仅针对按降序排序的前10个州):

GET /bank/_search
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "state.keyword"
},
"aggs": {
"average_balance": {
"avg": {
"field": "balance"
}
}
}
}
}
}

请注意我们如何嵌套average_balance聚合内的group_by_state聚合。这是所有聚合的常见模式。您可以在聚合中任意嵌套聚合,以从数据中提取所需的轮转摘要。

在前一个聚合的基础上,我们现在按降序排列平均余额:

GET /bank/_search
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "state.keyword",
"order": {
"average_balance": "desc"
}
},
"aggs": {
"average_balance": {
"avg": {
"field": "balance"
}
}
}
}
}
}

此示例演示了我们如何按年龄段(20-29岁,30-39岁和40-49岁)进行分组,然后按性别分组,最后得到每个年龄段的平均帐户余额:

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"
}
}
}
}
}
}
}
}

还有许多其他聚合功能,我们在此不再详述。如果您想进行进一步的实验,聚合参考指南是一个很好的起点。

总结

本篇文章依据官方文档,实践了查询和聚合命令,前面查询的部分还是很简单的,聚合这块有些复杂。
本篇到此结束,感谢观看。有兴趣的可以通过 http://www.weixinhe.cn:5601 演示上述命令。

ElasticSearch实践系列(三):探索数据的更多相关文章

  1. ElasticSearch实战系列三: ElasticSearch的JAVA API使用教程

    前言 在上一篇中介绍了ElasticSearch实战系列二: ElasticSearch的DSL语句使用教程---图文详解,本篇文章就来讲解下 ElasticSearch 6.x官方Java API的 ...

  2. [ 搭建Redis本地服务器实践系列三 ] :图解Redis客户端工具连接Redis服务器

    上一章 [ 搭建Redis本地服务器实践系列二 ] :图解CentOS7配置Redis  介绍了Redis的初始化脚本文件及启动配置文件,并图解如何以服务的形式来启动.终止Redis服务,可以说我们的 ...

  3. ASP.NET Web API实践系列07,获取数据, 使用Ninject实现依赖倒置,使用Knockout实现页面元素和视图模型的双向绑定

    本篇接着上一篇"ASP.NET Web API实践系列06, 在ASP.NET MVC 4 基础上增加使用ASP.NET WEB API",尝试获取数据. 在Models文件夹下创 ...

  4. ElasticSearch实践系列(二):探索集群

    前言 为了方便ELK的逐步搭建,我们本篇文章先安装Kibana,然后用Kibana的DevTols执行命令.也可以安装elasticsearch-head运行命令. 安装Kibana 参考Instal ...

  5. 机器学习基础与实践(三)----数据降维之PCA

    写在前面:本来这篇应该是上周四更新,但是上周四写了一篇深度学习的反向传播法的过程,就推迟更新了.本来想参考PRML来写,但是发现里面涉及到比较多的数学知识,写出来可能不好理解,我决定还是用最通俗的方法 ...

  6. 学习ASP.NET Core Razor 编程系列三——创建数据表及创建项目基本页面

    一.创建脚本工具并执行初始迁移 在本节中,您将使用包管理控制台(PMC)来更新数据库: •添加VisualStudio Web代码生成包.这个包是运行脚本引擎所必需的. • 执行Add-Migrati ...

  7. Elasticsearch实践(三):Mapping

    版本:Elasticsearch 6.2.4. Mapping类似于数据库中的表结构定义,主要作用如下: 定义Index下字段名(Field Name) 定义字段的类型,比如数值型,字符串型.布尔型等 ...

  8. ElasticSearch实践系列(一):安装

    Elasticsearch简介 Elasticsearch是一个高度可扩展的开源全文搜索和分析引擎.它允许您快速,近实时地存储,搜索和分析大量数据.它通常用作底层引擎/技术,为具有复杂搜索功能和要求的 ...

  9. ElasticSearch优化系列三:机器设置(内存)

    heap参数设置优化 命令行修改 ./bin/elasticsearch -Xmx10g -Xms10g xmx-JVM最大允许分配的堆内存,按需分配 xms-JVM初始分配的堆内存 此值设置与-Xm ...

随机推荐

  1. 山西WebGIS项目总结

    有一段时间没写blog了,说实话,最近的心态一直在变化,看了一部日剧,回想了这一年所学所见,感觉生活目标变了. 做国土项目这段时间不是很忙,由于数据一直给不到位,时间拖得很久,所以在这期间也在继续学习 ...

  2. python第十九天——感冒中

    ConfigParser模块,hashlib模块,hmac模块: 创建配置文件: import configparser config = configparser.ConfigParser()#创建 ...

  3. 浅谈C#依赖注入

    什么是依赖注入?不管是js中的一些前端框架还是,java,C#,php等中的一些后端开发框架中,都会涉及这个看着逼格略高的词语:依赖注入,越是看着好像很厉害的东西越是会让许多人学习产生恐惧,好像很厉害 ...

  4. Linux 查看本机串口方法

    最近在了解嵌入式方面的知识,就随笔记录一下: 查看Linux本机串口: 1.查看串口是否可用 可以对串口发送数据比如对com1口,echo /dev/ttyS02.查看串口名称使用 ls -l /de ...

  5. Django电商项目---完成购物车页面day4

    创建购物车项目App python manage.py startapp df_cart 初始化项目: manas/urls.py manas/settings.py 创建新文件:df_cart/ur ...

  6. MATLAB数值分析实验

    1.用Newton迭代法求方程   的第一个正根. 作者:凯鲁嘎吉 - 博客园http://www.cnblogs.com/kailugaji/ newton.m: function x1=newto ...

  7. NavigationController相关颜色设置

    一.当push进去一个界面后,返回按钮颜色改变: self.navigationController.navigationBar.tintColor = [UIColor whiteColor];

  8. 学生&部门智能匹配程序

    Github链接 结对成员: 031502308 付逸豪 031502113 胡俊钦 数据生成 样例链接: 来点我啊 由于在生成数据的时候做了很多符合实际情况的限制,所以生成的数据都挺好的,就随便选了 ...

  9. 软件工程实践_结对Task2_ student_department_matching

    1. 给出结对成员的学号及姓名. 结对成员 031502506 陈龙江 031502529 王国超 click 2.首页给出项目的Github链接. github:传送门 3. 贴出你们生成的一组最& ...

  10. Excel中row函数的使用方法

    1.row函数的含义 1 row函数的含义 返回所选择的某一个单元格的行数. END 2.row函数的语法格式 1 row函数的语法格式 =row(reference) 如果省略reference,则 ...