Elasticsearch入门四:Elasticsearch-搜索、过滤、聚合


title: Elasticsearch入门四:Elasticsearch-搜索、过滤、聚合(译)
date: 2018-11-01 17:00:00
tags: Elasticsearch

原文地址:

https://www.elastic.co/guide/en/elasticsearch/reference/current/_exploring_your_data.html

一.搜索 API

搜索的REST API可以从_search端点访问。这个示例返回customer索引中的所有文档:

GET /event_search/_search?q=*&sort=id:asc&pretty

几个搜索参数的意思:

  • q=* :匹配索引中的所有文档

  • sort=id:asc : 所有文档按照id升序排序

  • pretty : 格式化JSON输出

响应如下:

{
	"took" : 207,
	"timed_out" : false,
	"_shards" : {
		"total" : 5,
		"successful" : 5,
		"failed" : 0
	},

	"hits" : {
		"total" : 16107987,
		"max_score" : null,
		"hits" : [
 	 	{
    		"_index" : "event_search",
    		"_type" : "app_sjyx_event",
    		"_id" : "00000092-bda7-48de-80ef-1cee534aa5e7",
    		"_score" : null,
   			"_source" : {
      			"id" : "00000092-bda7-48de-80ef-1cee534aa5e7",
      			"event" : "wxid_winbzgzpq7fg12:我今天把超梦种族一弄"
    		},
    		"sort" : [
      			"00000092-bda7-48de-80ef-1cee534aa5e7"
    		]
  		},
		{
    		"_index" : "event_search",
    		"_type" : "app_sjyx_event",
    		"_id" : "00000111-9a7c-483e-80fb-3313a4c9a8ce",
    		"_score" : null,
    		"_source" : {
      			"id" : "00000111-9a7c-483e-80fb-3313a4c9a8ce",
      			"event" : "通话时长 03:38"
    		},
    		"sort" : [
      			"00000111-9a7c-483e-80fb-3313a4c9a8ce"
   	 		]
  		}
 	]
 }
}

关于响应,我们看到以下部分:

  • took – 搜索时间(毫秒)

  • timed_out – 搜索是否超时

  • _shards – 告诉我们搜索了多少碎片,以及成功/失败搜索碎片的计数

  • hits – 搜索结果

  • hits.total – 符合我们搜寻条件的文件总数

  • hits.hits – 实际的搜索结果数组(默认为前10个文档)

  • hits.sort 结果的排序键(如果按分数排序,则会丢失)

使用以下的方法可以达到相同的搜索结果:

POST /event_search/_search
{
	"query": { "match_all": {} },
	"sort": [
		{ "id": "asc" }
	]
}

很重要的一点是,一旦返回搜索结果,Elasticsearch就完全完成了对请求的处理,不会在结果中维护任何类型的服务器端资源或打开游标,这不同于SQL。

二.查询 DSL

查询DSL是json风格的域特定查询语句,查询语句非常全面,我们先从几个基本的例子入手。

1.按id升序查询10到19的文档

POST /event_search/_search
{
	"query": { "match_all": {} },
	"sort": [
		{ "id": "asc" }
	],
	"from": 10,
	"size": 10
}

搜索参数含义:

  • “query”:查询参数,match_all 指搜索所有的索引

  • “sort”:排序规则

  • “from”:指定从哪个文档索引开始,默认为0

  • “size”:指定从from参数开始返回多少文档

2.查询event字段中包含喜欢或推销的文档,文档只返回id,event两个字段

POST /event_search/_search
{
	 "query": { "match": { "event": "喜欢 推销" } },
	 "_source": ["id", "event"]
}
  • “_source”:指定返回的字段

3.查询event字段中包含喜欢且包含推销的文档

POST /event_search/_search
{
	"query": { "match_phrase": { "event": "喜欢 推销" } }
}

由以上两例可以看出match查询条件是的关系,而match_phrase查询条件是的关系

4.bool查询语句

bool查询允许我们使用布尔逻辑将较小的查询组合成较大的查询

以下例子包含两个匹配查询,并返回地址中包含“mill”“lane”的所有帐户:

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

与此相反,这个示例包含两个匹配查询,并返回地址中包含“mill”“lane”的所有帐户:

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

这个示例包含两个匹配查询,并返回地址中既不包含“mill”也不包含“lane”的所有帐户:

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

这个示例返回所有40岁但不生活在ID(阿霍)中的人的帐户:

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

三.过滤器

在上一节中,我们跳过了一个名为document score(搜索结果中的_score字段)的小细节。分数是一个数值,它是文档与我们指定的搜索查询匹配程度的相对度量。分数越高,文档越相关,分数越低,文档越不相关。

但是查询并不总是需要产生scores,特别是当它们仅用于“过滤”文档集时。Elasticsearch检测到这些情况并自动优化查询执行,以便不计算无用的分数。

我们在前一节中介绍的bool查询还支持filter子句,该子句允许使用查询来限制其他子句匹配的文档,而不改变计算分数的方式。作为一个例子,让我们引入range查询,它允许我们通过一系列值筛选文档。这通常用于数字或日期过滤。

以下示例使用bool查询返回所有余额在20000到30000之间的帐户(包括在内)。换句话说,我们希望找到的账户余额大于等于20000,小于等于30000:

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

四.聚合

聚合提供了从数据中分组和提取统计信息的能力。考虑聚合最简单的方法是将其大致等同于SQL GROUP by和SQL聚合函数。在Elasticsearch中,您可以执行返回命中的搜索,同时在一个响应中返回与所有命中分离的聚合结果。这在某种意义上非常强大和高效,因为您可以运行查询和多个聚合,并一次性获得两个(或两个以上)操作的结果,从而减少网络资源调用的损耗。

首先,这个示例按状态对所有帐户进行分组,然后返回按计数递减排序的前10个(默认):

GET /bank/_search
{
	"size": 0,
	"aggs": {
		"group_by_state": {
  		"terms": {
    		"field": "state"
  		 }
	 	}
	}
}

在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(爱达荷州)有27个账户,TX(德克萨斯州)有27个账户,AL(阿拉巴马州)有25个账户,等等。

注意,我们将size=0设置为不显示搜索结果,因为我们只想看到响应中的聚合结果。

注意我们如何将average_balance聚合嵌套到group_by_state聚合中。这是所有聚合的常见模式。

在前面的聚合的基础上,现在让我们按降序对平均余额进行排序:

GET /bank/_search
{
	"size": 0,
	"aggs": {
		"group_by_state": {
 		"terms": {
    		"field": "state",
    		"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"
      	},
      	"aggs": {
        	"average_balance": {
          	"avg": {
            	"field": "balance"
          	  }
           }
        }
      }
    }
   }
  }
}

还有很多其他的聚合功能我们在这里不会详细介绍。如果您想做进一步的实验,聚合参考指南是一个很好的起点。

五.总结

Elasticsearch是一个简单的和复杂的产品。到目前为止,我们已经了解了它是什么,如何查看它的内部,以及如何使用一些REST api使用它。希望本教程能让您更好地理解Elasticsearch是什么,更重要的是,它激发了您对其其他强大功能的进一步试验!

猜你喜欢

转载自blog.csdn.net/sunjian1122/article/details/83653808