ES-API开发常用功能

ES-API开发常用功能

创建索引

1.创建索引的索引名称必须为小写,大写会报错。
2.当没有为创建的索引指定Mapping时,es会为索引指定默认的Mapping(eg:字符串默认给keyword)。当查询的时候发现查不到,就有可能是忘记设置Mapping导致类型不对,无法进行分词检索。
3.当索引需要使用别名查询或者删除时,在创建索引的时候要为索引起别名。

es.addAlias([索引名], [别名]);

插入索引

1.将list插入索引中,使用现有框架的方法异步插入即可,注意数据类型的正确性(eg:数值类型的字段如果写成keyword将不能区间查询)。

查询索引

通过KQL进行查询

GET /temp.alias/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "projName": {
              "value": "帅气"
            }
          }
        }
      ]
    }
  }
}

通过ES的Java-API对索引文档进行条件查询

1.首先创建搜索请求对象SearchRequest

SearchRequest searchRequest = new SearchRequest(TEMP_ALIAS);

2.创建BoolQueryBuilder对象,进行筛选条件填充(类似于sql的where的条件查询must[and]should[or])。BoolQueryBuilder可以多次定义,嵌套使用。

BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

其中查询的方式主要有以下几种:

分词查询

只能作用于text类型的字段。对关键词先进行分词处理,然后查询。Operator.AND表示对分词结果的条件进行and筛选,Operator.OR表示对分词结果进行or筛选

boolQueryBuilder.must(new MatchQueryBuilder("name", bo.getKeyword()).analyzer("ik_smart").operator(Operator.AND));
短语查询

有的需求需要支持像类似于mysql的模糊查询,例如名称/地址等条件搜索框。

MatchPhraseQueryBuilder name = QueryBuilders.matchPhraseQuery("name", name);
多条件and查询

当条件是集合入参时,使用termsQuery,类似于sql的in;单个入参时使用termQuery,类似于sql的=。

boolQueryBuilder.must(QueryBuilders.termsQuery("name", nameList));
boolQueryBuilder.must(QueryBuilders.termQuery("name", name));
多条件should查询
QueryBuilders.boolQuery().should();
嵌套查询
boolQueryBuilder.must(QueryBuilders.boolQuery());
范围查询
QueryBuilders.rangeQuery("date").gt(dateMin).lt(dateMax);
数组查询

数组查询只需要按照mapping的层级结构.对应的属性即可,其他查询方法完全相同。

boolQueryBuilder.must(QueryBuilders.rangeQuery("datre").gt(dateMin).lt(dateMax));
半径搜索

半径搜索功能需要在索引的时候建立特有的geo_point类型。

boolQueryBuilder.must(QueryBuilders.geoDistanceQuery("location")
                    .point(location.getLat(),location.getLon()).
                            distance(distance.toString(), DistanceUnit.KILOMETERS));
聚合查询-count

例如统计某个字段分别有多少条记录,类似与sql的count(*)

  • 条件组装

    sourceBuilder.aggregation(AggregationBuilders.terms("propertyTypeAgg").field("cityId"));
    
  • 结果值的获取

    private Map<String,String> getCountAggByName(SearchResponse response, String name) {
            Map<String,String> brandMap = new HashMap<>();
            Aggregations aggregations = response.getAggregations();
            // 4.1.根据聚合名称获取聚合结果
            Terms brandTerms = aggregations.get(aggName);
            // 4.2.获取buckets
            List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
            // 4.3.遍历
            for (Terms.Bucket bucket : buckets) {
                // 4.4.获取key
                String key = bucket.getKeyAsString();
                long docCount = bucket.getDocCount();
                brandMap.put(key,String.valueOf(docCount));
            }
            return brandMap;
    }
    
聚合查询-sum,max,min,avg,mid

​ 例如要统计某个字段的最大值、最小值,平均值,中位数,汇总值,要求该字段必须为数字类型,不然会抛出异常:需要数字类型,但得到了[keyword]。类似与sql对应的同名函数。

  • 条件组装

    //最大值、最小值,平均值,中位数,汇总值sourceBuilder.aggregation(AggregationBuilders.stats("startingPriceAgg").field("startingPrice"));
    //中位数(50代表取50%的数据)       sourceBuilder.aggregation(AggregationBuilders.percentiles("buildAreaAgg").field("buildArea").percentiles(50));
    
  • 结果值的获取

    private Map<String,String> getMetricsAggByName(SearchResponse response, String name) {
            Map<String,String> brandMap = new HashMap<>();
            Aggregations aggregations = response.getAggregations();
            //1.根据聚合名称获取聚合结果
            ParsedStats aggregation = aggregations.get(aggName);
            //2.获取值
            brandMap.put("max",aggregation.getMaxAsString());
            brandMap.put("min",aggregation.getMinAsString());
            brandMap.put("avg",aggregation.getAvgAsString());
            brandMap.put("sum",aggregation.getSumAsString());
            return brandMap;
    }
    private Map<String,String> getMiddleAggByName(SearchResponse response, String aggName) {
            Map<String,String> brandMap = new HashMap<>();
            Aggregations aggregations = response.getAggregations();
            //1.根据聚合名称获取聚合结果
            ParsedTDigestPercentiles aggregate = aggregations.get(aggName);
            //2.获取buckets
            brandMap.put("mid",aggregate.percentileAsString(50));
            return brandMap;
    }
    
聚合查询-区间段聚合

如果要根据单价段、面积段等区间条件聚合,就需要用到range聚合。

  • 条件组装

    //区间分组查询
    sourceBuilder.aggregation(AggregationBuilders.range("buildAreaRangeAgg")
                    .field("buildArea")
                    .addUnboundedTo("100以下", 100)
                    .addRange("100-200", 100,200)
                    .addUnboundedFrom("200以上", 200));
    
  • 结果值获取

    private Map<String,String> getRangeAggByName(SearchResponse response, String name) {
            Map<String,String> brandMap = new HashMap<>();
            Aggregations aggregations = response.getAggregations();
            // 4.1.根据聚合名称获取聚合结果
            ParsedRange aggregation = aggregations.get(aggName);
            // 4.2.获取buckets
            List<? extends Range.Bucket> buckets = aggregation.getBuckets();
            for (Range.Bucket bucket : buckets) {
                // 4.4.获取key
                String key = bucket.getKeyAsString();
                long docCount = bucket.getDocCount();
                brandMap.put(key,String.valueOf(docCount));
            }
            return brandMap;
    }
    

3.创建SearchSourceBuilder查询对象,并进行查询

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(boolQueryBuilder);

4.分页(类似于mysql的limit)

sourceBuilder.from((page - 1) * pageSize).size(pageSize);

5.排序(类似于sql的order by)

sourceBuilder.sort(orderColumn, SortOrder.ASC);

6.设置查询的超时时间

sourceBuilder.timeout(new TimeValue(10, TimeUnit.SECONDS));

7.set进搜索请求对象

searchRequest.source(sourceBuilder);

8.发起请求进行搜索

SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
部分响应字段:
RestStatus status = searchResponse.status();//响应状态
TimeValue took = searchResponse.getTook();//查询时间
Boolean terminatedEarly = searchResponse.isTerminatedEarly();//请求是否提前终止
boolean timedOut = searchResponse.isTimedOut();//是否超时
response.getHits().totalHits;//命中次数

9.以Json-String或者map的形式获得查询结果。

String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();  

一般用法

//声明接收结果的集合
List<TempDto> tempList = new ArrayList<>();
//遍历结果
Arrays.stream(response.getHits().getHits()).forEach(i -> {
	try {
		//通过jackson的ObjectMapper转化为对象
		TempDtoDoc d = new ObjectMapper().readValue(i.getSourceAsString(),TempDtoDoc.class);
		TempDto temp= new TempDto();
		BeanUtils.copyProperties(d, temp);
		//add到我们需要的list中
		tempList.add(temp);
	} catch (IOException e) {
		logger.error(e.getMessage());
	}
});  

推荐

在代码调试的过程中发现代码查不到数据,可以在拼接好查询条件后search之前打断点,拿到sourceBuilder的Json串,放到Kibana界面进行查询,寻找原因,这样可以更加直观的看到各个条件之间的逻辑关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值