重学Elasticsearch第5章 : 过滤查询、聚合查询


Filter Query(过滤查询)

过滤查询

其实准确来说,ES中的查询操作分为2种: 查询(query)过滤(filter)

  • 查询即是之前提到的query查询,它(查询)默认会计算每个返回文档的得分,然后根据得分排序
  • 过滤(filter)只会筛选出符合的文档,并不计算得分,且它可以缓存文档 。所以,单从性能考虑,过滤比查询更快

换句话说,过滤适合在大范围筛选数据,而查询则适合精确匹配数据。一般应用时, 应先使用过滤操作过滤数据, 然后使用查询匹配数据。

在这里插入图片描述

过滤语法

// 从所有文档中过滤age>=10的文档
GET /ems/_search
{
  "query": {
    "bool": {
      "must": [
        {"match_all": {}}
      ],
      "filter": {
        "range": {
          "age": {
            "gte": 10
          }
        }
      }
    }
  }
}

提示: 在执行filter和query时,先执行filter在执行query

提示: Elasticsearch会自动缓存经常使用的过滤器,以加快性能。

常见的过滤器类型

term 、terms Filter

// 先过滤出content字段关键词为spring的文档,再query出name为黑的文档
GET /ems/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "name": {
              "value": "黑"
            }
          }
        }
      ],
      "filter": {
        "term": {
          "content":"spring"
        }
      }
    }
  }
}

// 找到content中过滤不包含 科技,声音的文档, 然后在进行term关键词查询name为中国的文档
GET /dangdang/_search  #使用terms过滤
{
  "query": {
    "bool": {
      "must": [
        {"term": {
          "name": {
            "value": "中国"
          }
        }}
      ],
      "filter": {
        "terms": {
          "content":[
              "科技",
              "声音"
            ]
        }
      }
    }
  }
}

ranage filter

GET /ems/_search
{
  "query": {
    "bool": {
      "must": [
        {"term": {
          "name": {
            "value": "中国"
          }
        }}
      ],
      "filter": {
        "range": {
          "age": {
            "gte": 7,
            "lte": 20
          }
        }
      }
    }
  }
}

exists filter

过滤出存在指定字段的文档

// 首先过滤出存在name字段的文档,并且进行term关键词查询,name字段中包含中国的文档
GET /ems/_search
{
  "query": {
    "bool": {
      "must": [
        {"term": {
          "name": {
            "value": "中国"
          }
        }}
      ],
      "filter": {
        "exists": {
          "field":"name"
        }
      }
    }
  }
}

ids filter

过滤含有指定字段的索引记录

GET /ems/_search
{
  "query": {
    "bool": {
      "must": [
        {"term": {
          "name": {
            "value": "中国"
          }
        }}
      ],
      "filter": {
        "ids": {
          "values": ["1","2","3"]
        }
      }
    }
  }
}

聚合查询

简介

聚合:英文为Aggregation,是es除搜索功能外提供的针对es数据做统计分析的功能。聚合有助于根据搜索查询提供聚合数据。

聚合查询是数据库中重要的功能特性,ES作为搜索引擎兼数据库,同样提供了强大的聚合分析能力。它基于查询条件来对数据进行分桶、计算的方法。有点类似于 SQL 中的 group by 再加一些函数方法的操作。

注意事项:text类型是不支持聚合的。

测试数据

// 创建索引 index 和映射 mapping
PUT /fruit
{
  "mappings": {
    "properties": {
      "title":{
        "type": "keyword"
      },
      "price":{
        "type":"double"
      },
      "description":{
        "type": "text",
        "analyzer": "ik_max_word"
      }
    }
  }
}
// 放入测试数据
PUT /fruit/_bulk
{"index":{}}
  {"title" : "面包","price" : 19.9,"description" : "小面包非常好吃"}
{"index":{}}
  {"title" : "旺仔牛奶","price" : 29.9,"description" : "非常好喝"}
{"index":{}}
  {"title" : "日本豆","price" : 19.9,"description" : "日本豆非常好吃"}
{"index":{}}
  {"title" : "小馒头","price" : 19.9,"description" : "小馒头非常好吃"}
{"index":{}}
  {"title" : "大辣片","price" : 39.9,"description" : "大辣片非常好吃"}
{"index":{}}
  {"title" : "透心凉","price" : 9.9,"description" : "透心凉非常好喝"}
{"index":{}}
  {"title" : "小浣熊","price" : 19.9,"description" : "童年的味道"}
{"index":{}}
  {"title" : "海苔","price" : 19.9,"description" : "海的味道"}

使用

根据某个字段分组

// 根据检索条件查询出来的文档, 进行分组;根据price进行分组,分组叫price_group
GET /fruit/_search
{
  "query": {
    "term": {
      "description": {
        "value": "吃"
      }
    }
  }, 
  "aggs": {
    "price_group": {
      "terms": {
        "field": "price"
      }
    }
  }
}
// 结果
{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 0.6489038,
    "hits" : [
      {
        "_index" : "fruit",
        "_type" : "_doc",
        "_id" : "xbUHXYIBkJ4IdFBIeDXc",
        "_score" : 0.6489038,
        "_source" : {
          "title" : "面包",
          "price" : 19.9,
          "description" : "小面包非常好吃"
        }
      },
      {
        "_index" : "fruit",
        "_type" : "_doc",
        "_id" : "x7UHXYIBkJ4IdFBIeDXc",
        "_score" : 0.6489038,
        "_source" : {
          "title" : "日本豆",
          "price" : 19.9,
          "description" : "日本豆非常好吃"
        }
      },
      {
        "_index" : "fruit",
        "_type" : "_doc",
        "_id" : "yLUHXYIBkJ4IdFBIeDXc",
        "_score" : 0.6489038,
        "_source" : {
          "title" : "小馒头",
          "price" : 19.9,
          "description" : "小馒头非常好吃"
        }
      },
      {
        "_index" : "fruit",
        "_type" : "_doc",
        "_id" : "ybUHXYIBkJ4IdFBIeDXc",
        "_score" : 0.6489038,
        "_source" : {
          "title" : "大辣片",
          "price" : 39.9,
          "description" : "大辣片非常好吃"
        }
      }
    ]
  },
  "aggregations" : {
    "price_group" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : 19.9,
          "doc_count" : 3
        },
        {
          "key" : 39.9,
          "doc_count" : 1
        }
      ]
    }
  }
}

求最大值

# 求最大值 
GET /fruit/_search
{
  "aggs": {
    "price_max": {
      "max": {
        "field": "price"
      }
    }
  }
}

在这里插入图片描述

求最小值

# 求最小值
GET /fruit/_search
{
  "aggs": {
    "price_min": {
      "min": {
        "field": "price"
      }
    }
  }
}

在这里插入图片描述

求平均值

# 求平均值
GET /fruit/_search
{
  "aggs": {
    "price_agv": {
      "avg": {
        "field": "price"
      }
    }
  }
}

在这里插入图片描述

求和

# 求和
GET /fruit/_search
{
  "aggs": {
    "price_sum": {
      "sum": {
        "field": "price"
      }
    }
  }
}

在这里插入图片描述

聚合查询整合Java

// 求不同价格的数量
@Test
public void testAggsPrice() throws IOException {
  SearchRequest searchRequest = new SearchRequest("fruit");
  SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
  sourceBuilder.aggregation(AggregationBuilders.terms("group_price").field("price"));
  searchRequest.source(sourceBuilder);
  SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  Aggregations aggregations = searchResponse.getAggregations();
  ParsedDoubleTerms terms = aggregations.get("group_price");
  List<? extends Terms.Bucket> buckets = terms.getBuckets();
  for (Terms.Bucket bucket : buckets) {
    System.out.println(bucket.getKey() + ", "+ bucket.getDocCount());
  }
}
// 求不同名称的数量
@Test
public void testAggsTitle() throws IOException {
  SearchRequest searchRequest = new SearchRequest("fruit");
  SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
  sourceBuilder.aggregation(AggregationBuilders.terms("group_title").field("title"));
  searchRequest.source(sourceBuilder);
  SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  Aggregations aggregations = searchResponse.getAggregations();
  ParsedStringTerms terms = aggregations.get("group_title");
  List<? extends Terms.Bucket> buckets = terms.getBuckets();
  for (Terms.Bucket bucket : buckets) {
  	System.out.println(bucket.getKey() + ", "+ bucket.getDocCount());
  }
}
// 求和
@Test
public void testAggsSum() throws IOException {
  SearchRequest searchRequest = new SearchRequest("fruit");
  SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
  sourceBuilder.aggregation(AggregationBuilders.sum("sum_price").field("price"));
  searchRequest.source(sourceBuilder);
  SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  ParsedSum parsedSum = searchResponse.getAggregations().get("sum_price");
  System.out.println(parsedSum.getValue());
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

white camel

感谢支持~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值