ElasticSearch从入门到精通(持续更新....)—多条件查询(聚合查询)

951 阅读3分钟

这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战

(持续更新....)

昨天学习了ElasticSearch的多条件查询,对查询有了基本的理解,但是这只限于控制台,其实开发过程中需要Java代码实现ElasticSearch查询。

本文基于ElasticSearch和kabana的7.x版本。

一、java查询应用

1、添加RestHighLevelClient依赖

<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>7.13.4</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.13.4</version>
</dependency>

2、配置RestHighLevelClient

@Configuration
public class ElasticSearchConfig {

    @Value("${xxxx.host}")
    private String hostname;
    @Value("${xxxx.port}")
    private int port;
    @Value("${xxxx.user}")
    private String user;
    @Value("${xxxx.password}")
    private String password;
    @Value("${xxxx.timeout}")
    private long socketTimeout;
    @Value("${xxxx.scheme}")
    private String scheme;

    public static final RequestOptions COMMON_OPTIONS;

    static {
        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
        COMMON_OPTIONS = builder.build();
    }

    /**
     *  使用账号密码连接
     **/
    public RestHighLevelClient restClient() {
        RestClientBuilder builder = RestClient.builder(
                new HttpHost(hostname, port, scheme));
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(user, password));
        builder.setHttpClientConfigCallback(f -> f.setDefaultCredentialsProvider(credentialsProvider));
        return new RestHighLevelClient(builder);
    }

}

3、组装查询条件--分页


@Autowired
RestHighLevelClient esSafeRestClient;


SearchSourceBuilder builder = new SearchSourceBuilder();
EsQueryBuilderUtil.setPage(requestOptions);
builder.from(requestOptions.getPageNum()-1);
builder.size(requestOptions.getPageSize());
BoolQueryBuilder must = QueryBuilders.boolQuery();

//组装查询条件
TermsQueryBuilder queryBuilder = QueryBuilders.termsQuery("workOrderFlowId", id);
...

//时间降序
builder.sort(new FieldSortBuilder("startTime").order(SortOrder.DESC));
builder.trackTotalHits(true);
builder.query(must);

4、查询处理

String index = "t_xxxx_xx";

SearchRequest request = new SearchRequest(new String[]{index});
CountRequest countRequest = new CountRequest(new String[]{index});
countRequest.source(builder);
request.source(builder);

try {
    SearchResponse response = this.esSafeRestClient.search(request, ElasticSearchConfig.COMMON_OPTIONS);
    this.esSafeRestClient.count(countRequest, RequestOptions.DEFAULT);
    SearchHits hits1 = response.getHits();
    long length = hits1.getTotalHits().value;
    SearchHit[] hits2 = hits1.getHits();
    List<T> retList = new ArrayList(hits2.length);
    SearchHit[] var13 = hits2;
    int var14 = hits2.length;

    for(int var15 = 0; var15 < var14; ++var15) {
        SearchHit hit = var13[var15];
        String strJson = hit.getSourceAsString();
        retList.add(JSON.parseObject(strJson, reference, new Feature[0]));
    }

    EsPageDto<T> pageDto = new EsPageDto();
    pageDto.setTotal(length);
    pageDto.setList(retList);
    return pageDto;
} catch (Exception var18) {
    var18.printStackTrace();
    throw new RuntimeException(var18);
}

二、几种查询方法封装

//range query
//范围查询
//QueryBuilders.rangeQuery("hotelNo") .gt("10143262306")//大于 10143262306
// .lt("101432623062055348221") //小于 101432623062055348221
// .includeLower(true) //包括下界
// .includeUpper(false); //包括上界
public void rangeQuery(String name, Long startTime, Long endTime, BoolQueryBuilder must) {
    must.must(QueryBuilders.rangeQuery(name).from(startTime).to(endTime));
}

// exist query 查询字段不为null的文档 如查询字段name 不为null的数据
public void existQuery(String name, BoolQueryBuilder must) {
    must.must(QueryBuilders.existsQuery(name));
}

// mustNot 查询没有字段或值为null或没有值的文档
public void notExistQuery(String name, BoolQueryBuilder must) {
    must.mustNot(QueryBuilders.existsQuery(name));
}

//prefix query 匹配分词前缀 如果字段没分词,就匹配整个字段前缀
public void prefixQuery(String name, String value,  BoolQueryBuilder must) {
    must.must(QueryBuilders.prefixQuery(name, value));
}

//matchAllQuery匹配所有
//matchPhraseQuery对中文精确匹配
//matchQuery("key", Obj) 单个匹配, field不支持通配符, 前缀具高级特性
public void matchPhraseQuery(String name, Object value, BoolQueryBuilder must) {
    if (!Objects.isNull(value)) {
        must.must(QueryBuilders.matchPhraseQuery(name, value));
    }
}

//multiMatchQuery("text", "field1", "field2"..); 一个值匹配多个字段, field有通配符忒行
public void multiMatchQuery(String field1, String field2,String field3,Object value, BoolQueryBuilder must) {
    if (!Objects.isNull(value)) {
        must.must(QueryBuilders.multiMatchQuery(value, field1, field2, field3));
    }
}

//matchPhraseQuery对中文精确匹配前缀
public void matchPhrasePrefixQuery(String name, Object value, BoolQueryBuilder must) {
    if (!Objects.isNull(value)) {
        must.must(QueryBuilders.matchPhrasePrefixQuery(name, value));
    }
}

//分词精确查询
public void termQuery(String name, Object value, BoolQueryBuilder must) {
    if (!Objects.isNull(value)) {
        must.must(QueryBuilders.termQuery(name, value));
    }
}

//terms Query 多term查询,匹配多个值
public void termsQuery(String name, List<String> value, BoolQueryBuilder must) {
    if (!Objects.isNull(value)) {
        must.must(QueryBuilders.termsQuery(name, value));
    }
}

//组合查询
//* must:   AND
//* mustNot: NOT
//* should:: OR
public void shouldQuery(String name, Object value, BoolQueryBuilder must) {
    if (!Objects.isNull(value)) {
        must.should(QueryBuilders.termsQuery(name, value));
    }
}

// 模糊查询
//wildcard query 通配符查询,支持* 任意字符串;?任意一个字符
public void wildcardQuery(String name, Object value, BoolQueryBuilder must) {
    if (!Objects.isNull(value)) {
        must.must(QueryBuilders.wildcardQuery(name+".keyword", "*" + value+"*"));
    }
}

//regexp query 正则表达式匹配分词
public void regexpQuery(String name, Object value, BoolQueryBuilder must) {
    if (!Objects.isNull(value)) {
        must.must(QueryBuilders.regexpQuery(name, "../"));
    }
}

//fuzzy query 分词模糊查询,通过增加fuzziness 模糊属性,来查询term
// 如下 能够匹配 name 为 te el tel前或后加一个字母的term的
// 文档 fuzziness 的含义是检索的term 前后增加或减少n个单词的匹配查询
public void fuzzyQuery(String name, Object value, BoolQueryBuilder must) {
    if (!Objects.isNull(value)) {
        must.must(QueryBuilders.fuzzyQuery(name, value).fuzziness(Fuzziness.ONE));
    }
}

三、聚合查询

聚合函数:使用AggregationBuilders

AggregationBuilder aggregation =
		AggregationBuilders.terms("as_code").field("code.keyword")
				.subAggregation(AggregationBuilders.terms("group_category").field("category")		.subAggregation(AggregationBuilders.max("max_index").field("traffic_index"))
				)
				.size(Integer.MAX_VALUE);
                                
                                
//统计code个数,去重
AggregationBuilders.cardinality("distinct_code").field("code");
//统计最大分
AggregationBuilders.max("max_score").field("score");
//统计最小分
AggregationBuilders.min("min_score").field("score");
//统计总分和
AggregationBuilders.sum("sum_score").field("score");
//统计平均分
AggregationBuilders.avg("avg_score").field("score");

四、查询指定几个字段

setFetchSource(String[] includes, String[] excludes)方法指定所需的字段 sourceBuilder.fetchSource("shop_code", null);//过滤门店编码为null数据

SearchResponse response = client.prepareSearch("my-index")
   .setTypes("my-type")
   .setSearchType(SearchType.QUERY_AND_FETCH)
   .setFetchSource(new String[]{"field1"}, null)
   .setQuery(QueryBuilders.termsQuery("field1", "1234"))
   .execute()
   .actionGet();

for (SearchHit hit : response.getHits()){
   Map map = hit.getSource();
   map.toString();
}

今天就到这里,明天继续。