elasticsearch聚合及查询详细报文

本文介绍了如何使用Elasticsearch进行复杂查询和聚合操作,包括基于JSON报文的查询示例,涉及must、should、mustnot和wildcardQuery等查询类型。同时探讨了分组和聚合的应用,如TermsAggregation,以及在不同索引数量和分片大小下的性能影响。文章强调了合理设置索引和分片的重要性,以及在跨索引查询和聚合操作中的注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文基于elasticsearch java客户端elasticsearch-5.5.2.jar

在工作中遇到一些问题,存储大量数据,本来是计划用OpenTSDB存储这些数据,因为这些数据可以描述为点,具有比较明确的时序特性,但实际中用的OpenTSDB不稳定,并且调研发现ES也可以存这批数据,相对来讲扩展性更好,但需要做好跨索引的工作。

查询

json报文格式:

{
  "query": {
    "bool": {
      "must": [   
        {
          "term": {
            "src": "10.10.169.145" 
          }
        },
        {
          "term": {
            "app": "中文"
          }
        },
        {
          "term": {
            "appid": "test"
          }
        },
        {
          "range": {
            "timestamp.long": {
              "gt": "1544510518758",
              "lt": "1544511518758"
            }
          }
        }
      ],
      "should": [
        {
          "term": {
            "id": "test.id"
          }
        }
      ]
    }
  },
  "from": 0,
  "size": 10000,
  "sort": [],
  "aggs": {
    
    }
  }
}

以上报文匹配appid为test,app为中文,src为10.10.169.145,timestamp时间范围为1544510518758到1544511518758,并且id可以为test.id的文档,其中包括must查询和should查询,must查询为全匹配,should可以理解为或,其它查询还有mustnot为非,wildcardQuery查询为模糊匹配。

String index = "index";
String aes1 = "x*";
String aes2 = "g*";
String appid="";
String appgroup="";
long startTime = Long.parseLong(start);
long endTime = Long.parseLong(end);

BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
queryBuilder.must(QueryBuilders.wildcardQuery("src",  aes1));
queryBuilder.must(QueryBuilders.wildcardQuery("target",  aes2));
queryBuilder.must(QueryBuilders.termQuery("appid", appid));
queryBuilder.must(QueryBuilders.termQuery("appgroup", appgroup));
queryBuilder.must(QueryBuilders.rangeQuery("timestamp").gte(startTime).lte(endTime));

ESClient client = new ESClient("127.0.0.1:9300", "");  // 连接到客户端
SearchResponse sResponse  = client.getClient().prepareSearch(index)  // 要查询的索引,如果是跨索引查询输入String数组
                .setTypes(IndexMgr.TEST_Table)  // table类型,索引之下的一个类型,对应放数据时候的类型
                .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) //查询方式
                .setQuery(queryBuilder)  //查询条件
                .setSize(10000)  // 返回的doc的个数
                .get(TimeValue.timeValueMillis(5000));  // 超时时间

分组及聚合

有时候查询的时候需要用的分组,并且聚合的情况

{
    "query":{
        "bool":{
            "must":[
                {
                    "term":{
                        "src":"10.10.169.145"
                    }
                },
                {
                    "term":{
                        "app":"中文"
                    }
                },
                {
                    "term":{
                        "appid":"test"
                    }
                },
                {
                    "range":{
                        "timestamp.long":{
                            "gt":"1544510518758",
                            "lt":"1544511518758"
                        }
                    }
                }
            ],
            "should":[
                {
                    "term":{
                        "id":"test.id"
                    }
                }
            ]
        }
    },
    "from":0,
    "size":0,
    "sort":[

    ],
    "aggs":{
        "urilist":{
            "terms":{
                "field":"uri"
            },
            "aggs":{
                "total":{
                    "sum":{
                        "field":"total"
                    }
                },
                "add":{
                    "sum":{
                        "field":"add"
                    }
                }
            }
        }
    }
}

以上是一个查询并且聚合的报文,query中是查询文档的一系列条件,aggs中是分组和聚合相关报文,urilist为分组的名字,自己取名,uri为分组的字段,里面还有个aggs,代表对已经分组的文档进行内部聚合,这里的聚合对total和add两个字段作了加和。

    String index = "index";
    String aes1 = "x*";
    String aes2 = "g*";
    String appid="";
    String appgroup="";
    long startTime = Long.parseLong(start);
    long endTime = Long.parseLong(end);
    
    BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
    queryBuilder.must(QueryBuilders.wildcardQuery("src",  aes1));
    queryBuilder.must(QueryBuilders.wildcardQuery("target",  aes2));
    queryBuilder.must(QueryBuilders.termQuery("appid", appid));
    queryBuilder.must(QueryBuilders.termQuery("appgroup", appgroup));
    queryBuilder.must(QueryBuilders.rangeQuery("timestamp").gte(startTime).lte(endTime));
    
   TermsAggregationBuilder srclist =    AggregationBuilders.terms("urilist").field("uri").size(10000);  // 设置返回的分组数,如果不设置默认是10
    AggregationBuilder total =AggregationBuilders.sum("total").field("total");
    AggregationBuilder add =AggregationBuilders.sum("add").field("add");
    srclist.subAggregation(total);
    srclist.subAggregation(add);

    ESClient client = new ESClient("127.0.0.1:9300", "");  // 连接到客户端
    SearchResponse sResponse  = client.getClient().prepareSearch(index)  // 要查询的索引,如果是跨索引查询输入String数组
                    .setTypes(IndexMgr.TEST_Table)  // table类型,索引之下的一个类型,对应放数据时候的类型
                    .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) //查询方式
                    .setQuery(queryBuilder)  //查询条件
                    .setSize(0)  // 返回的doc的个数为0,因为只需要分组结果
                    .addAggregation(agg) //添加聚合
                    .get(TimeValue.timeValueMillis(5000));  // 超时时间

TermsAggregation聚合器默认是查询top N的项目,如果不设置聚合大小,默认是10。

相关测试及注意问题

  1. 索引分片大小合适的大小为50G左右
  2. 跨索引查询的情况下,会比单索引情况下慢,以下单索引查询,跨20个索引,跨60个索引查询,以及各文档个数情况下测试的一些数据(没有足够考虑缓存的情况下,不能说很精确),但能看出几个趋势:
  • 单索引查询情况下在测试文档个数范围内,文档个数对查询效率的影响比较小;
  • 多索引查询比单索引查询慢,大概在3到5倍
  • 同文档数情况下聚合比查询要快(可以看看倒排索引相关文档,我理解为已经天然分好了组)
  • 单索引聚合和多索引聚合相比,多索引聚合要慢,但差距比多索引查询比单索引查询小很多(1到2倍)
  1. 建立合适的索引,做好分索引的工作,如果数据不长期存放是最好的
    在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值