本章内容概述
1、布尔查询
2、聚合查询
1、布尔查询Bool Query
Elasticsearch在2.x版本的时候把filter查询给摘掉了,因此在query dsl里面已经找不到filter query了。其实es并没有完全抛弃
filter query,而是它的设计与之前的query太重复了。因此直接给转移到了bool查询中。
Bool查询现在包括四种子句,must,filter,should,must_not。
1.1 为什么filter会快?
看上面的流程图就能很明显的看到,filter与query还是有很大的区别的。
比如,query的时候,会先比较查询条件,然后计算分值,最后返回文档结果;
而filter则是先判断是否满足查询条件,如果不满足,会缓存查询过程(记录该文档不满足结果);满足的话,就直接缓存结果。
综上所述,filter快在两个方面:
1 对结果进行缓存
2 避免计算分值
1.2 bool查询的使用
Bool查询对应Lucene中的BooleanQuery,它由一个或者多个子句组成,每个子句都有特定的类型。
must:返回的文档必须满足must子句的条件,并且参与计算分值
filter:返回的文档必须满足filter子句的条件。但是不会像Must一样,参与计算分值
should:返回的文档可能满足should子句的条件。在一个Bool查询中,如果没有must或者filter,有一个或者多个should子句,那么
只要满足一个就可以返回。minimum_should_match参数定义了至少满足几个子句。
must_nout:返回的文档必须不满足must_not定义的条件。
更多内容请参考:https://www.cnblogs.com/xing901022/p/5994210.html
1.2.1 数据准备
批量添加数据:
POST /lib4/items/_bulk
{"index":{"_id":1}}
{"price":40,"itemID":"ID100123"}
{"index":{"_id":2}}
{"price":50,"itemID":"ID100124"}
{"index":{"_id":3}}
{"price":25,"itemID":"ID100125"}
{"index":{"_id":4}}
{"price":30,"itemID":"ID100126"}
{"index":{"_id":5}}
{"price":null,"itemID":"ID100127"}
1.2.2 filter查询
1、查询价格为40的商品
### 过滤price是40的商品
GET /lib4/items/_search
{
"query": {
"bool": {
"filter": [
{"term":{"price":40}}
]
}
}
}
2、查询价格为25或40的商品
GET /lib4/items/_search
{
"query": {
"bool": {
"filter": [
{"terms":{"price":[25,40]}}
]
}
}
}
3、查询商品编号为ID100123的商品
GET /lib4/items/_search
{
"query": {
"bool": {
"filter": [
{"term":{"itemID":"ID100123"}}
]
}
}
}
结果发现,什么都没有查到,原因在于我们使用的是动态映射,分词器会把ID100123进行分词,ID转换为小写的id,我们只需要把ID改为小
写即可。
当然,我们也可以使用静态映射来定义;
PUT /lib4
{
"mappings": {
"items":{
"properties":{
"itemID":{
"type":"text",
"index":false
}
}
}
}
}
略
4、过滤商品价格为25-50之间的商品
gt 相当于 >
lt 相当于 <
gte 相当于 >=
lte 相当于 <=
GET /lib4/items/_search
{
"query": {
"bool": {
"filter":{
"range":{
"price":{
"gt":25,
"lt":50
}
}
}
}
}
}
5、过滤价格不为空的商品
GET /lib4/items/_search
{
"query": {
"bool": {
"filter":{
"exists": {
"field": "price"
}
}
}
}
}
1.2.3 bool查询查询
可以实现组合过滤查询
格式:
"bool": {
"must": [
{}
],
"should": [
{}
],
"must_not": [
{}
]
}
must:必须满足的条件 --->and
shouid:可以满足也可以不满足的条件 --->or
must_not:不需要满足的条件 --->not
1、查询价格是25或商品id为id100123,但是价格不能是40的
GET /lib4/items/_search
{
"query": {
"bool": {
"should": [
{"term": {
"price": {
"value": 25
}
}},
{
"term": {
"itemID": {
"value": "id100123"
}
}
}
],
"must_not": [
{
"term": {
"price": {
"value": 40
}
}
}
]
}
}
}
2、查询商品编号是id100123的 或者 必须同时满足商品编号是100124和价格为40的
GET /lib4/items/_search
{
"query": {
"bool": {
"should": [
{"term":{"itemID": "id100123"}},
{
"bool": {
"must": [
{"term":{"itemID": "id100123"}},
{"term":{"price": 40}}
]
}
}
]
}
}
}
2、聚合查询
类似于关系型数据库的最大值、最小值、平均值、求和等
语法规则:
GET /索引名/类型/_search
{
"aggs":{
"聚合结果变量名":{
"sum/max/min/avg等":{
"field":"指定字段"
}
}
}
}
"aggs" 用来定义聚合查询
1、查询所有商品的总价格
GET /lib4/items/_search
{
"aggs":{
"price_of_sum":{
"sum":{
"field":"price"
}
}
}
}
我们会发现,查询出来的结果里面参照了很多商品数据
结果:
{
"took": 66,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 5,
"max_score": 1,
"hits": [
{
"_index": "lib4",
"_type": "items",
"_id": "5",
"_score": 1,
"_source": {
"price": null,
"itemID": "ID100127"
}
},
{
"_index": "lib4",
"_type": "items",
"_id": "2",
"_score": 1,
"_source": {
"price": 50,
"itemID": "ID100124"
}
},
{
"_index": "lib4",
"_type": "items",
"_id": "4",
"_score": 1,
"_source": {
"price": 30,
"itemID": "ID100126"
}
},
{
"_index": "lib4",
"_type": "items",
"_id": "1",
"_score": 1,
"_source": {
"price": 40,
"itemID": "ID100123"
}
},
{
"_index": "lib4",
"_type": "items",
"_id": "3",
"_score": 1,
"_source": {
"price": 25,
"itemID": "ID100125"
}
}
]
},
"aggregations": {
"price_of_sum": {
"value": 145
}
}
}
我们如果为了精简看结果,可以通过size来改变现实数量:
GET /lib4/items/_search
{
"size": 0,
"aggs":{
"price_of_sum":{
"sum":{
"field":"price"
}
}
}
}
2、查询价格最低的商品
GET /lib4/items/_search
{
"size": 0,
"aggs":{
"price_of_min":{
"min":{
"field":"price"
}
}
}
}
3、查询价格最高的商品
GET /lib4/items/_search
{
"size": 0,
"aggs":{
"price_of_max":{
"max":{
"field":"price"
}
}
}
}
4、查询所有商品的平均价格
GET /lib4/items/_search
{
"size": 0,
"aggs":{
"price_of_avg":{
"avg":{
"field":"price"
}
}
}
}
5、求价格的基数:基数指的是所有价格不同的数量
GET /lib4/items/_search
{
"size": 0,
"aggs":{
"price_of_cardinality":{
"cardinality":{
"field":"price"
}
}
}
}
6、根据价格分组查询:价格相同的一组
POST /lib4/items/_bulk
{"index":{"_id":6}}
{"price":30,"itemID":"ID100127"}
GET /lib4/items/_search
{
"size": 0,
"aggs":{
"price_of_group":{
"terms":{
"field":"price"
}
}
}
}
7、综合练习:对那些有唱歌兴趣的用户按年龄分组[使用之前的user]
GET /lib3/user/_search
{
"query": {
"match": {
"interests": "唱歌"
}
},
"aggs": {
"age_of_group": {
"terms": {
"field": "age"
}
}
}
}
8、综合练习:对那些有唱歌兴趣的用户按年龄分组,分组之后求每一组的平均年龄
GET /lib3/user/_search
{
"query": {
"match": {
"interests": "唱歌"
}
},
"aggs": {
"age_of_group": {
"terms": {
"field": "age"
},
"aggs": {
"age_of_avg": {
"avg": {
"field": "age"
}
}
}
}
}
}
“aggs”: {
“age_of_group”: {
“terms”: {
“field”: “age”
}
}
}
}
8、综合练习:对那些有唱歌兴趣的用户按年龄分组,分组之后求每一组的平均年龄
GET /lib3/user/_search
{
“query”: {
“match”: {
“interests”: “唱歌”
}
},
“aggs”: {
“age_of_group”: {
“terms”: {
“field”: “age”
},
“aggs”: {
“age_of_avg”: {
“avg”: {
“field”: “age”
}
}
}
}
}
}