learn-tech/专栏/ElasticSearch知识体系详解/04入门:查询和聚合的基础使用.md
2024-10-16 00:01:16 +08:00

6.8 KiB
Raw Blame History

                        因收到Google相关通知网站将会择期关闭。相关通知内容
                        
                        
                        04 入门:查询和聚合的基础使用
                        入门:从索引文档开始

索引一个文档

PUT /customer/_doc/1 { "name": "John Doe" }

为了方便测试我们使用kibana的dev tool来进行学习测试

查询刚才插入的文档

学习准备:批量索引文档

ES 还提供了批量操作,比如这里我们可以使用批量操作来插入一些数据,供我们在后面学习使用。

使用批量来批处理文档操作比单独提交请求要快得多,因为它减少了网络往返。

下载测试数据

数据是index为bankaccounts.json 下载地址 如果你无法下载也可以clone ES的官方仓库 ,然后进入/docs/src/test/resources/accounts.json目录获取

数据的格式如下

{ "account_number": 0, "balance": 16623, "firstname": "Bradshaw", "lastname": "Mckenzie", "age": 29, "gender": "F", "address": "244 Columbus Place", "employer": "Euron", "email": "[email protected]", "city": "Hobucken", "state": "CO" }

批量插入数据

将accounts.json拷贝至指定目录我这里放在/opt/下面,

然后执行

curl -H "Content-Type: application/json" -XPOST "localhost:9200/bank/_bulk?pretty&refresh" --data-binary "@/opt/accounts.json"

查看状态

[elasticsearch@VM-0-14-centos root]$ curl "localhost:9200/_cat/indices?v=true" | grep bank % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 1524 100 1524 0 0 119k 0 --:--:-- --:--:-- --:--:-- 124k yellow open bank yq3eSlAWRMO2Td0Sl769rQ 1 1 1000 0 379.2kb 379.2kb [elasticsearch@VM-0-14-centos root]$

查询数据

我们通过kibana来进行查询测试。

查询所有

match_all表示查询所有的数据sort即按照什么字段排序

GET /bank/_search { "query": { "match_all": {} }, "sort": [ { "account_number": "asc" } ] }

结果

相关字段解释

took Elasticsearch运行查询所花费的时间以毫秒为单位 timed_out –搜索请求是否超时 _shards - 搜索了多少个碎片,以及成功,失败或跳过了多少个碎片的细目分类。 max_score 找到的最相关文档的分数 hits.total.value - 找到了多少个匹配的文档 hits.sort - 文档的排序位置(不按相关性得分排序时) hits._score - 文档的相关性得分使用match_all时不适用

分页查询(from+size)

本质上就是from和size两个字段

GET /bank/_search { "query": { "match_all": {} }, "sort": [ { "account_number": "asc" } ], "from": 10, "size": 10 }

结果

指定字段查询match

如果要在字段中搜索特定字词可以使用match; 如下语句将查询address 字段中包含 mill 或者 lane的数据

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

结果

由于ES底层是按照分词索引的所以上述查询结果是address 字段中包含 mill 或者 lane的数据

查询段落匹配match_phrase

如果我们希望查询的条件是 address字段中包含 “mill lane”则可以使用match_phrase

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

结果

多条件查询: bool

如果要构造更复杂的查询可以使用bool查询来组合多个查询条件。

例如以下请求在bank索引中搜索40岁客户的帐户但不包括居住在爱达荷州ID的任何人

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

结果

must, should, must_not 和 filter 都是bool查询的子句。那么filter和上述query子句有啥区别呢

查询条件query or filter

先看下如下查询, 在bool查询的子句中同时具备query/must 和 filter

GET /bank/_search { "query": { "bool": { "must": [ { "match": { "state": "ND" } } ], "filter": [ { "term": { "age": "40" } }, { "range": { "balance": { "gte": 20000, "lte": 30000 } } } ] } } }

结果

两者都可以写查询条件而且语法也类似。区别在于query 上下文的条件是用来给文档打分的,匹配越好 _score 越高filter 的条件只产生两种结果:符合与不符合,后者被过滤掉。

所以我们进一步看只包含filter的查询

GET /bank/_search { "query": { "bool": { "filter": [ { "term": { "age": "40" } }, { "range": { "balance": { "gte": 20000, "lte": 30000 } } } ] } } }

结果显然无_score

聚合查询Aggregation

我们知道SQL中有group by在ES中它叫Aggregation即聚合运算。

简单聚合

比如我们希望计算出account每个州的统计数量 使用aggs关键字对state字段聚合被聚合的字段无需对分词统计所以使用state.keyword对整个字段统计

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

结果

因为无需返回条件的具体数据, 所以设置size=0返回hits为空。

doc_count表示bucket中每个州的数据条数。

嵌套聚合

ES还可以处理个聚合条件的嵌套。

比如承接上个例子, 计算每个州的平均结余。涉及到的就是在对state分组的基础上嵌套计算avg(balance):

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

结果

对聚合结果排序

可以通过在aggs中对嵌套聚合的结果进行排序

比如承接上个例子, 对嵌套计算出的avg(balance)这里是average_balance进行排序

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

结果