TopHits聚合

聚合后,每一个聚合Bucket里面仅返回指定顺序的前N条数据。

应用场景

例如可以展示出某一个网站文档浏览前N名的文档,es中储存的数据是用户每点击一次文档即浏览一次文档就会对文档进行储存

{
  "size": 0,  // 仅过滤数据,不返回命中数据。
  "query": {
    "bool": {
      "must": [  // 过滤条件,在聚合前先进行数据筛选。
        {
          "terms": {
            "del": [
            	0
            ]
          }
        }
      ]
    }
  },
  "aggs": {
    "agg": {  // 第一层聚合:先按照team_id将数据聚合成多个Bucket。
      "terms": {
        "field": script{
        			type=inline, 
        			lang='painless', 
        		    idOrCode='doc['language'].value+'@'+doc['data_id'].value', 
        		    options={},
        		    params={}
        		    } // 按照数据id和语言进行分组计数
      },
      "aggs": {
        "top": {  // 第二层聚合:在第一层聚合结果中的每个Bucket内,在进行top_hits聚合操作。
          "top_hits": {
            "size": 1,  // 仅返回前1条记录
            "sort": [   // 排序条件按照score倒序
              {
                "score": {
                  "field": "time",
                  "order": "desc"
                }
              }
            ]
          }
        }
      }
    }
  }
}

java代码示例

public void topHitsTest() {
        SearchRequestBuilder searchRequestBuilder = transportClient.prepareSearch(IndexEnum.BEHAVIOR_DOCUMENT.getIndex());
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        // 查询基本条件
        boolQueryBuilder
                .mustNot(QueryBuilders.termQuery(BehaviorDocumentFieldEnum.del.name(), Constants.YES));

        String top = "top";
        // 生成一个按照上传时间排序的语句
        AggregationBuilder topAgg = AggregationBuilders.topHits(top)
                .size(1).sort(BehaviorDocumentFieldEnum.time.name(), SortOrder.DESC);
        String agg = "agg";
        Script primaryScript = new Script(ScriptType.INLINE, "painless",
                "doc['" + BehaviorDocumentFieldEnum.language.name() + "'].value +'" + Constants.SEPARATOR_AT + "'+doc['" + BehaviorDocumentFieldEnum.data_id.name() + "'].value",
                new HashMap<>(0));
         // aggregationBuilder构建一个按照语言和data_id进行分组的操作,子聚合中按照时间进行排序       
        AggregationBuilder aggregationBuilder = AggregationBuilders
                .terms(agg)
                .script(primaryScript)
                .subAggregation(topAgg);
		// 获取相关的数据
        SearchResponse searchResponse = searchRequestBuilder
                .setQuery(boolQueryBuilder)
               .addAggregation(aggregationBuilder)
                .setSize(0)
                .get();
        // 得到聚合的map集合        
        Map<String, Aggregation> stringAggregationMap = searchResponse.getAggregations().asMap();
        // 得到Terms聚合部分
        StringTerms stringTerms = (StringTerms) stringAggregationMap.get(agg);
        // 循环遍历得到topHits中的数据
        for (Terms.Bucket bucket : stringTerms.getBuckets()) {
            StringTerms.Bucket buck = (StringTerms.Bucket) bucket;
            TopHits tophits = buck.getAggregations().get(top);
            SearchHits tophitsHits = tophits.getHits();
            SearchHit hit = tophitsHits.getHits()[0];
            // 得到相关的数据
            Map<String, Object> stringObjectMap = hit.sourceAsMap();
            // 浏览次数
            buck.getDocCount();
			// 后续可以通过JSON相关的工具来赋值进相关的对象
           
        }
    }
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐