接下来我们来简单了解下,数据的搜索,过滤,聚合等操作。
准备数据
首先创建一份银行账户数据。他的格式为:
{
"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"
}
可以通过bulk语法来批量创建数据,数据地址
搜索语法
搜索语法有两种方式,一种是在url里面带上查询条件,另一种是在请求体里面传递查询条件。请求体查询可以使用更加丰富的JSON进行查询。官方建议还用请求体的方式去查询数据。
下面是搜索使用url的示例:
GET /customer/_search?q=*&sort=account_number:asc
这里我们搜索了客户信息,然后q=*表示搜索当前索引下的所有文档。sort=account_number:asc表示对搜索结果按照account_number正序排。pretty表示用漂亮的json格式输出。
部分返回值
{
"took": 8,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1000,
"relation": "eq"
},
"max_score": null,
"hits": [
{
"_index": "customer",
"_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:es搜索的时间,单位为毫秒。
-
timed_out:告诉我们搜索是否超时。
-
_shards:告诉我们搜索了多少分片 ,以及成功和失败分片的数量。
-
hits:搜索结果。
-
hits.total:查询结果的总数相关的信息对象。
- hits.total.value:总共搜索的结果 (需要根据
hits.total.relation
来解释这个值)。 - hits.total.relation:如果值为eq,表示刚好等于
hits.total.value
的值。如果值为gte,表示大于等于hits.total.value
的值。
- hits.total.value:总共搜索的结果 (需要根据
-
hits.hits:实际数组的搜索结果。默认返回10条文档。
-
hits.sort:结果排序的key (如果按score排序,改字段就消失)
-
hits.hits._score:当前文档的得分。
-
hits.max_score:当前结果的最大得分。
可以设置track_total_hits
为true,来准确的计数。
上面示例可以用请求体的方式替换为:
GET /customer/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"account_number": "asc"
}
]
}
这里使用json格式的请求体来调用_search接口。
es的搜索直接把结果返回给你了,不会在服务端打开游标。这个跟其他的关系型数据库有所区别。
介绍搜索语法
es提供json格式的查询语法,他被称为:Query DSL。查询语法非常丰富。
"query": { "match_all": {} }
像query,表示这个是一个查询。match_all表示查询的类型。
match_all表示查询所有的文档。
处理query条件外,我们还可以指定其他条件,想sort、size、from等来影响查询结果。
GET /customer/_search
{
"query":{"match_all":{}},
"size":1
}
如果size没有指定,那么默认为10。
from参数:表示从哪个基数开始,默认是0。
size参数:表示取多少文档。
from和size在实现分页的时候非常有用。
sort参数:表示对某些属性进行排序。
深入了解搜索
match_all
默认情况下,查询的结果会所有文档属性都返回,一般用_source来表示。如果你想指定具体某几个属性返回,那么可以在查询中指定。如下:
GET /customer/_search
{
"query":{"match_all":{}},
"_source":["account_number", "balance"]
}
返回值
{
"took": 92,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1000,
"relation": "eq"
},
"max_score": 1,
"hits": [
{
"_index": "customer",
"_type": "_doc",
"_id": "1",
"_score": 1,
"_source": {
"account_number": 1,
"balance": 39225
}
},
。。。。
]
}
}
可以看出,结果只返回了查询中指定的字段。跟sql中的 select 某字段 from 某表 有点类似。
match
搜索可以对某个字段进行准确搜索。如:
GET /customer/_search
{
"query": {
"match": {
"account_number": 20
}
}
}
上面的搜索是查找出account_number=20的数据。
mach_phrase
搜索匹配是否包含查询内容。
GET /customer/_search
{
"query": {
"match_phrase": {
"address": "lane"
}
}
}
上面例子搜索出address属性包含lane的数据。
bool query
可以把几个小的查询条件组合成一个大的查询条件。如下例子:
GET /customer/_search
{
"query":{
"bool":{
"must":[
{"match":{"address":"mill"}},
{"match":{"address":"lane"}}
]
}
}
}
上面例子会查询出address同时包含mill和lane的数据。
must表示所有条件必须满足,相当于sql中的and。
should表示只要满足其中一个条件就可以,相当于sql中的or。
GET /customer/_search
{
"query":{
"bool":{
"should":[
{"match":{"address":"mill"}},
{"match":{"address":"lane"}}
]
}
}
}
示例表示,只要包含mill或者lane其中一个就可以。
must_not表示都不包含。
GET /customer/_search
{
"query":{
"bool":{
"must_not":[
{"match":{"address":"mill"}},
{"match":{"address":"lane"}}
]
}
}
}
示例表示既不包含mill,也不包含lane。
当然你可以在bool里面同时使用must、should、must_not。也可以在bool里面在使用bool。
GET /customer/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"age": 40
}
}
],
"must_not": [
{
"match": {
"state": "ID"
}
}
]
}
}
}
示例表示返回年龄在40岁且不住在ID的客户。
执行过滤器
之前有看到过_score属性,它表示这个查询结果的得分,得分越高,表示匹配的关联性越高;得分越低,表示匹配的关联性越低。当我们使用filter的时候,得分其实没有必要了。当在使用了filter之后,es会做一些优化,不会去计算这些得分。
像上面的bool查询,就可以使用filter,
GET /customer/_search
{
"query": {
"bool":{
"must":{"match_all":{}},
"filter":{
"range":{
"balance":{
"gte":20000,
"lte":30000
}
}
}
}
}
}
示例使用了范围查询,表示某个字段在一个范围内。这里表示balance>=20000且balance<=30000的客户。
过滤器的性能要高很多,因为他不需要计算得分,所以可以使用过滤器来完成的查询尽量使用过滤器。
聚合
聚合主要是把数据分组或者提取统计信息。你可以简单的理解为就是sql中的group by或者聚合函数。在es中,可以同时返回查询结果和聚合结果。这是非常高效的做法,不然你可能需要执行多次请求,去获取你想要的结果。
GET /customer/_search
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "state.keyword"
}
}
}
}
类似这样的sql
SELECT state, COUNT(*) FROM customer GROUP BY state ORDER BY COUNT(*) DESC LIMIT 10;
上面的示例表示不同的洲的客户个数,默认是按降序排。
部分返回值:
size表示显示查询结果内容数量。如果你只想看聚合结果,那么可以设置为0。
GET /customer/_search
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "state.keyword"
},
"aggs": {
"average_balance": {
"avg": {
"field": "balance"
}
}
}
}
}
}
示例表示在每个洲的平均账户余额。
部分返回值
{
。。。
"aggregations": {
"group_by_state": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 743,
"buckets": [
{
"key": "TX",
"doc_count": 30,
"average_balance": {
"value": 26073.3
}
},
。。。。
]
}
}
}
可以在聚合里面继续嵌套聚合,这样就可以对聚合结果在进行聚合。我们还可以对聚合结果进行排序。如:
GET /customer/_search
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "state.keyword",
"order":{
"average_balance":"desc"
}
},
"aggs": {
"average_balance": {
"avg": {
"field": "balance"
}
}
}
}
}
}
示例是对平均余额进行排序。
GET /customer/_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"
}
}
}
}
}
}
}
}
上面例子演示了我们如何按年龄级别(20-29岁、30-39岁和40-49岁)分组,然后按性别分组,最后得到每个年龄级别、每个性别的平均帐户余额。
返回值
{
。。。
"aggregations": {
"group_by_age": {
"buckets": [
{
"key": "20.0-30.0",
"from": 20,
"to": 30,
"doc_count": 451,
"group_by_gender": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "M",
"doc_count": 232,
"average_balance": {
"value": 27374.05172413793
}
},
{
"key": "F",
"doc_count": 219,
"average_balance": {
"value": 25341.260273972603
}
}
]
}
},
{
"key": "30.0-40.0",
"from": 30,
"to": 40,
"doc_count": 504,
"group_by_gender": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "F",
"doc_count": 253,
"average_balance": {
"value": 25670.869565217392
}
},
{
"key": "M",
"doc_count": 251,
"average_balance": {
"value": 24288.239043824702
}
}
]
}
},
。。。
]
}
}
}
以上是比较简单的聚合方法示例。
注意:本文归作者所有,未经作者允许,不得转载