elasticsearch自定义分数、优化聚合、桶聚合、别名搜索

本文详细介绍了Elasticsearch中别名的使用,自定义分数查询,以及聚合查询的方法。通过别名实现索引的灵活切换,自定义分数查询结合布尔查询和函数评分实现复杂的数据排序,同时展示了如何利用脚本评分和时间字段调整权重。在聚合查询部分,分别演示了获取最小值、最大值以及IP分布的示例,最后讨论了Elasticsearch的多种聚合类型及其应用场景。

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

一、别名
索引别名可以指向一个或多个索引,并且可以在任何需要索引名称的API中使用。 别名为我们提供了极大的灵活性。在正在运行的集群上的一个索引和另一个索引之间透明切换;
1、别名搜索,alias_es_user是别名,_search是索引关键字。
在这里插入图片描述
2、创建别名
在这里插入图片描述

二、自定义分数查询

  SearchRequest searchRequest = new SearchRequest("es_user");
        //explain为true表示根据数据相关度排序,和关键字匹配最高的排在前面
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //搜索查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.should(QueryBuilders.fuzzyQuery("user_name","张"));

        //分数查询
        FunctionScoreQueryBuilder.FilterFunctionBuilder[] filterFunctionBuilders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[2];

        //过滤条件2:时间越早 优先级越高
        FieldValueFactorFunctionBuilder fieldValueScoreFunction = new FieldValueFactorFunctionBuilder("post_date")
                  //reciprocal 报答字段值,同1/x那里x是该字段的值
                  .modifier(FieldValueFactorFunction.Modifier.RECIPROCAL)
                  .factor(0.1f);
        filterFunctionBuilders[0] = new FunctionScoreQueryBuilder.FilterFunctionBuilder(fieldValueScoreFunction);

        //过滤条件3:使用 Script 写js 进行判断分数
        ScriptScoreFunctionBuilder scoreFunctionBuilder = ScoreFunctionBuilders.scriptFunction(new Script("return doc ['user_name'].value == '张三' ? 1.9 : 1.0"));
        filterFunctionBuilders[1] =  new FunctionScoreQueryBuilder.FilterFunctionBuilder(scoreFunctionBuilder);


        // 多条件查询 FunctionScore  例如:2 分(有停车位)+ 1 分(有 wifi)+ 6 分(评分 5 分 \* 1.2)+ 1 分(随机评分)
        FunctionScoreQueryBuilder query = QueryBuilders.functionScoreQuery(boolQueryBuilder, filterFunctionBuilders)
                .scoreMode(FunctionScoreQuery.ScoreMode.SUM).boostMode(CombineFunction.SUM);

        //聚合查询
        AggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("user_name").field("team").executionHint("map");


        searchSourceBuilder.aggregation(termsAggregationBuilder);
        searchSourceBuilder.query(query);
        searchRequest.source(searchSourceBuilder);
        try {
            SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            SearchHit[] searchHits = response.getHits().getHits();
            log.info("当前查询分数结果:\n\n {} \n\n", JSON.toJSON(searchHits));
            if (searchHits == null || searchHits.length <= 0) {
                log.info("--------------搜索结果为空 ---------- ");
            }
            if(Objects.nonNull(searchHits)){
                for (SearchHit hit : searchHits) {
                    String sourceAsString = hit.getSourceAsString();
                    log.info("当前查询结果:{}", JSON.toJSON(sourceAsString));
                }
            }
        } catch (IOException e) {
            log.error(e.getMessage());
        }

语句:

GET es_user_aliase/_search
{
  "query": {
    "function_score": {
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "user_name": "张"
              }
            }
          ]
        }
      },
      "functions": [
        {
          "field_value_factor": {
                "field": "post_date",
                "modifier": "log",
                "factor": 0.1
            }
        },
        {
          "exp": {
            "post_date": {
              "origin": "2021-06-15",
              "scale": "1d",
              "decay": 0.9
            }
          }
        },
         {
          "script_score": {
            "script": "return doc ['age'].value != null ? (_score + 1.0) : (_score)"
          }
        }
      ],
      "boost_mode": "sum"
    }
  },
  "sort": {
    "_score": {
      "order": "desc"
    }
  }
}

三、聚合查询

    private Map<String, Object> getMin(Map<String, Object> map){
        SearchRequest searchRequest = new SearchRequest("es_user");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        AggregationBuilder avgAge = AggregationBuilders.min("min_time").field("post_date");
        searchSourceBuilder.aggregation(avgAge);
        searchSourceBuilder.size(0);
        searchRequest.source(searchSourceBuilder);
        SearchResponse response = null;
        try {
            response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        if(Objects.nonNull(response)){
            Aggregation minTime = response.getAggregations().get("min_time");
            System.out.println("-------"+JSON.toJSONString(minTime));
            map.put("min", minTime.getMetaData().get("valueAsString"));
        }
        return null;
    }


    private Map<String, Object> getMax(Map<String, Object> map){
        SearchRequest searchRequest = new SearchRequest("es_user");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        AggregationBuilder avgAge = AggregationBuilders.max("max_time").field("post_date");
        searchSourceBuilder.aggregation(avgAge);
        searchSourceBuilder.size(0);
        searchRequest.source(searchSourceBuilder);
        SearchResponse response = null;
        try {
            response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        if(Objects.nonNull(response)){
            Aggregation maxTime = response.getAggregations().get("max_time");
            System.out.println("-------"+JSON.toJSONString(maxTime));
            map.put("max", maxTime.getMetaData().get("valueAsString"));
        }
        return null;
    }


    private Map<String, Object> getIp(Map<String, Object> map){
        SearchRequest searchRequest = new SearchRequest("es_user");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //使用map方式优化聚合速度,原理:在内存聚合
        AggregationBuilder ipAggregation = AggregationBuilders.terms("ip_name").field("ip").executionHint("map");
        searchSourceBuilder.aggregation(ipAggregation);
        searchSourceBuilder.size(0);
        searchRequest.source(searchSourceBuilder);
        SearchResponse response = null;
        try {
            response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        if(Objects.nonNull(response)){
            Aggregation ipName = response.getAggregations().get("ip_name");
            System.out.println("-------"+JSON.toJSONString(ipName));
            map.put("ip", ipName.getMetaData().get("valueAsString"));
        }
        return null;
    }


    @Test
    public void test3(){
        Map<String, Object> map = new HashMap<>();
        CompletableFuture.allOf(
                CompletableFuture.supplyAsync(() -> getMin(map)),
                CompletableFuture.supplyAsync(() -> getMax(map)),
                CompletableFuture.supplyAsync(() -> getIp(map))
        ).join();
       System.out.println(JSON.toJSONString(map));
    }

四、聚合有哪些方式

Metric(指标): 指标分析类型,如计算最大值、最小值、平均值等等 (对桶内的文档进行聚合分析的操作)

#1、单值分析,只输出一个分析结果
min,max,avg,sum,cardinality
#2、多值分析,输出多个分析结果
stats,extended_stats,percentile,percentile_rank,top_hits

Bucket(桶): 分桶类型,类似SQL中的GROUP BY语法 (满足特定条件的文档的集合)
Pipeline(管道): 管道分析类型,基于上一级的聚合分析结果进行在分析
Matrix(矩阵): 矩阵分析类型(聚合是一种面向数值型的聚合,用于计算一组文档字段中的统计信息)

参考:https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html

聚合方法:

Avg Aggregation
Cardinality Aggregation
Extended Stats Aggregation
Geo Bounds Aggregation
Geo Centroid Aggregation
Max Aggregation
Min Aggregation
Percentiles Aggregation
Percentile Ranks Aggregation
Scripted Metric Aggregation
Stats Aggregation
Sum Aggregation
Top Hits Aggregation
Value Count Aggregation
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值