本文主要内容:
单条精准匹配查询
多条精准匹配查询
bool查询
过滤查询(范围查询)
执行聚合
分析查询返回内容
命令:GET sfeicuss/servicelog/_search
我们这里分析一下,成功请求后返回内容的含义:
{
"took": 124,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 5,
"max_score": 1,
"hits": [
{
"_index": "sfeicuss",
"_type": "servicelog",
"_id": "5",
"_score": 1,
"_source": {
"id": "1",
"service": "wangzha.company",
"appCode": "cms",
"source": "yidong",
"serviceResponseCode": "00004",
"bizResponseCode": "0",
"requestTime": "",
"responseTime": ""
}
},
{
"_index": "sfeicuss",
"_type": "servicelog",
"_id": "2",
"_score": 1,
"_source": {
"id": "1",
"service": "wangzha.company",
"appCode": "cms",
"source": "yidong",
"serviceResponseCode": "00001",
"bizResponseCode": "0",
"requestTime": "",
"responseTime": ""
}
},
{
"_index": "sfeicuss",
"_type": "servicelog",
"_id": "4",
"_score": 1,
"_source": {
"id": "1",
"service": "wangzha.company",
"appCode": "cms",
"source": "yidong",
"serviceResponseCode": "00003",
"bizResponseCode": "0",
"requestTime": "",
"responseTime": ""
}
},
{
"_index": "sfeicuss",
"_type": "servicelog",
"_id": "1",
"_score": 1,
"_source": {
"id": "1",
"service": "wangzha.company",
"appCode": "cms",
"source": "yidong",
"serviceResponseCode": "0000",
"bizResponseCode": "0",
"requestTime": "",
"responseTime": ""
}
},
{
"_index": "sfeicuss",
"_type": "servicelog",
"_id": "7",
"_score": 1,
"_source": {
"id": "1",
"service": "wangzha.company",
"appCode": "cms",
"source": "yidong",
"serviceResponseCode": "0000222",
"bizResponseCode": "0",
"requestTime": "",
"responseTime": ""
}
}
]
}
}
took:
Elasticsearch执行搜索的时间(以毫秒为单位)
timed_out:
告诉我们搜索是否超时
_shards:
告诉我们搜索了多少碎片,以及搜索碎片成功/失败的次数
hits:
搜索结果
hits.total:
符合我们搜索条件的文件总数
hits.hits:
实际的搜索结果数组(默认为前10个文档)
hits.sort:
对结果进行排序键(按分数排序时丢失)
排序查找:
GET /bank/_search
{
"query": { "match_all": {} },
"sort": [
{ "account_number": "asc" }
]
}
查询语言
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
(从0开始)参数规定了从启动该文件的索引和size参数指定了多少文件
,返回从参数开始的。此功能在实现分页搜索结果时非常有用。请注意,如果from未指定,则默认为0
。
此示例match_all
按帐户余额按降序排列结果并对结果进行排序,并返回前10个(默认大小)文档。
GET /bank/_search
{
"query": { "match_all": {} },
"sort": { "balance": { "order": "desc" } }
}
现在我们已经看到了一些基本的搜索参数,让我们进一步深入查询DSL。我们先来看看返回的文档字段。默认情况下,完整的JSON文档作为所有搜索的一部分返回。这被称为源(_source
搜索匹配中的字段)。如果我们不希望整个源文档被返回,我们有能力只需要返回源内的几个字段。请看下面的例子:
接下来,我们再看几种查询:
单条精准查询:
单条包含查询:
GET sfeicuss/servicelog/_search
{
"query":{
"match_phrase": {"service":"com"}
}
}
bool查询:
该bool查询允许我们撰写较小的查询到使用布尔逻辑更大的查询。
must:
必须有
should:
包含
must_not:
一定不
执行过滤器
在上一节中,我们跳过了一个称为文档分数(_score搜索结果中的字段)的细节。分数是一个数值,它是文档与我们指定的搜索查询匹配度的相对度量。分数越高,文档越相关,分数越低,文档的相关性越低。
但查询并不总是需要生成分数,特别是当它们仅用于“过滤”文档集时。Elasticsearch检测这些情况并自动优化查询执行,以便不计算无用分数。
我们在前一节中介绍的bool查询
还支持filter
使用查询来限制将被其他子句匹配的文档的子句,而不会更改计算分数的方式。作为一个例子,我们来介绍一下range查询,它允许我们通过一系列值来过滤文档。这通常用于数字或日期过滤。
示例:
该处是数字过滤。
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来避免网络往返。
示例一:对所有帐户进行分组,然后返回按降序(也是默认值)排序的前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
搜索结果的部分显示:
{
"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(爱达荷州)有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聚合。这是所有聚合的通用模式。您可以任意嵌套聚合内的聚合,以便从数据中提取所需的旋转摘要。
基于以前的汇总,现在让我们按降序对平均余额进行排序:
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d'
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "state.keyword"
},
"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"
}
}
}
}
}
}
}
}
还有其他许多聚合功能,我们在这里不会详细介绍。该聚合参考指南是一个很好的起点,如果你想要做进一步的实验。