Elasticsearch业务常用21种语句操作附Java Api代码

2,680 阅读8分钟

概述

我们操作数据习惯使用sql语句,对于非sql语句的数据库中间我们肯定使用得很不习惯.今天我要说的就是Elasticsearch,经常写过的一些语句,可能就忘记了,特别是写一些复杂查询的时候,更是到处百度资料,很是烦人.因此,我特地花了大量时间进行总结(包括 json格式语句和对应java api编写)

配置

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

直接导入依赖,然后注入RestHighLevelClient对象即可使用

基础增删改

添加文档

1.java api

/**
 * 添加文档
 * @param addDocDto
 * @throws IOException
 */
public void addDoc(AddDocDto addDocDto) throws IOException {

    IndexRequest indexRequest = new IndexRequest(addDocDto.getIndexName());

    indexRequest.source(addDocDto.getData());
    indexRequest.id(addDocDto.getId());
    //创建索引
    IndexResponse index = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);

    log.info("执行结果:"+JSONUtil.toJsonStr(index));
}
  1. elasticsearch语句
POST test-index-20220228/_doc
{
  "sex": "w",
  "balance2": 320,
  "balance": "501",
  "name": "liujing5",
  "age": 6
}

说明:用于插入文档,post方法 自动生成id

更新文档

1.java api

/**
 * 更新文档(仅仅根据id更新,是增量字段)
 * @param updateDocDto
 * @throws IOException
 */
public void updateDoc3(UpdateDocDto updateDocDto) throws IOException {

    UpdateRequest indexRequest = new UpdateRequest(updateDocDto.getIndexName(),updateDocDto.getId());

    //设置数据
    indexRequest.doc(updateDocDto.getData());

    //更新文档
    UpdateResponse update = restHighLevelClient.update(indexRequest, RequestOptions.DEFAULT);

    log.info("执行结果:"+JSONUtil.toJsonStr(update));
}

2.elasticsearch

POST test-index-20220228/_update/L1gtSX8BX_oAU-6DS9F3
{
  "doc": {
     "sex" : "w",
      "balance2" : 320,
      "balance" : "501",
      "name" : "liujing5",
      "age" : 7
  }
}

更新文档根据条件

1.java api

/**
 * 更新文档(根据条件更新数据,删掉了老字段)
 * @param updateDocDto
 * @throws IOException
 */
public void updateDoc2(UpdateDocDto updateDocDto) throws IOException {

    UpdateByQueryRequest indexRequest = new UpdateByQueryRequest(updateDocDto.getIndexName());

    //设置更新条件
    Set<String> strings = updateDocDto.getQuery().keySet();
    for (String key:strings){
        QueryBuilder queryBuilder = new TermQueryBuilder(key,updateDocDto.getQuery().get(key));
        indexRequest.setQuery(queryBuilder);
    }
    //设置更新值
    JSONObject data = updateDocDto.getData();

    //更新值脚本
    String source = "ctx._source=params";
    Script script = new Script(ScriptType.INLINE, "painless", source, data);
    indexRequest.setScript(script);

    //更新文档
    BulkByScrollResponse index = restHighLevelClient.updateByQuery(indexRequest, RequestOptions.DEFAULT);

    log.info("执行结果:"+JSONUtil.toJsonStr(index));
}

2.elasticsearch

POST test-index-20220228/_update_by_query
{
  "query": {
    "term": {
      "age": {
        "value" : 7,
        "boost" : 1.0
      }
    }
  },
  "script": {
    "source":"ctx._source=params", 
    "params":{"aaa":"50003"}
  }
}

说明: 根据任意条件更新匹配文档

删除文档

1.java api

/**
 * 删除文档(根据id)
 * @param deleteDocDto
 * @throws IOException
 */
public void deleteDoc(DeleteDocDto deleteDocDto) throws IOException {

    DeleteRequest indexRequest = new DeleteRequest(deleteDocDto.getIndexName(),deleteDocDto.getId());

    //更新文档
    DeleteResponse update = restHighLevelClient.delete(indexRequest, RequestOptions.DEFAULT);

    log.info("执行结果:"+JSONUtil.toJsonStr(update));
}

2.elasticsearch

DELETE test-index-20220228/_doc/L1gtSX8BX_oAU-6DS9F3

删除文档根据条件

1.java api

/**
 * 删除文档(根据任意条件)
 * @param deleteDocDto
 * @throws IOException
 */
public void deleteDoc2(DeleteDocDto deleteDocDto) throws IOException {

    DeleteByQueryRequest indexRequest = new DeleteByQueryRequest(deleteDocDto.getIndexName());

    //设置查询条件
    Set<String> strings = deleteDocDto.getQuery().keySet();
    for (String key:strings){
        QueryBuilder queryBuilder = new TermQueryBuilder(key,deleteDocDto.getQuery().get(key));
        indexRequest.setQuery(queryBuilder);
        log.info(queryBuilder.toString());
    }
    //更新文档
    BulkByScrollResponse response = restHighLevelClient.deleteByQuery(indexRequest, RequestOptions.DEFAULT);

    log.info("执行结果:"+JSONUtil.toJsonStr(response));
}

2.elasticsearch

POST test-index-20220228/_delete_by_query
{
  "query":{
    "term" : {
    "age" : {
      "value" : 6,
      "boost" : 1.0
    }
  }
  }
}

说明:根据条件删除指定文档

非分词基础查询(term)

单字段等值查询

1.类比mysql
select * from user where name = "张三"
2.java api

/**
 * 单字段查询(等值)
 * @param searchDocDto
 * @throws IOException
 */
public void search(SearchDocDto searchDocDto) throws IOException {

    //构件查询
    TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(searchDocDto.getKey(), searchDocDto.getValue());
    //查询
    searchCommon(searchDocDto.getIndexName(),termQueryBuilder);
}

3.elasticsearch

POST test-index-20220228/_search
{
  "query": {
    "term": {
      "name": {
        "value": "liujing2",
        "boost": 1
      }
    }
  }
}

说明: 可以进行任意单字段进行等值查询操作

单字段多值查询

1.类比mysql
select * from user where name in ("张三","李四")
2.java api

/**
 * 单字段查询(多值等值)
 * @param searchDocDto
 * @throws IOException
 */
public void search2(SearchDocDto searchDocDto) throws IOException {

    //构件查询
    TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery(searchDocDto.getKey(), searchDocDto.getValues());
    //查询
    searchCommon(searchDocDto.getIndexName(),termsQueryBuilder);
}

3.elasticsearch

POST test-index-20220228/_search
{
  "query": {
    "terms": {
      "name": [
        "liujing3",
        "liujing"
      ],
      "boost": 1
    }
  }
}

说明: 可以进行任意单字段多个值进行等值批量查询操作

分词基础查询(match)

单字段分词查询

1.类比mysql
select * from user where name like "%liujjing%"
2.java api

/**
 * 单字段查询(模糊-分词查询)
 * @param searchDocDto
 */
public void search11(SearchDocDto searchDocDto) throws IOException {
    //构件match查询
    MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(searchDocDto.getKey(), searchDocDto.getValue());

    //查询
    searchCommon(searchDocDto.getIndexName(),matchQueryBuilder);
}

3.elasticsearch

POST test-index-20220228/_search
{
  "query": {
    "match": {
      "name": {
        "query": "liujing2",
        "operator": "OR",
        "prefix_length": 0,
        "max_expansions": 50,
        "fuzzy_transpositions": true,
        "lenient": false,
        "zero_terms_query": "NONE",
        "auto_generate_synonyms_phrase_query": true,
        "boost": 1
      }
    }
  }
}

说明:可以对任意字段进行分词查询

多字段分词查询

1.类比mysql
select * from user where name like "%liujjing%" or ...
2.java api

/**
 * 多字段查询(模糊多个字段-分词查询)
 * @param searchDocDto
 */
public void search12(SearchDocDto searchDocDto) throws IOException {
    //构件match查询
    MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(searchDocDto.getValue(),searchDocDto.getFields());

    //查询
    searchCommon(searchDocDto.getIndexName(),multiMatchQueryBuilder);
}

3.elasticsearch

POST test-index-20220228/_search
{
  "query": {
    "multi_match": {
      "query": "liujing2 1200",
      "fields": [
        "name^1.0","balance"
      ],
      "type": "best_fields",
      "operator": "OR",
      "slop": 0,
      "prefix_length": 0,
      "max_expansions": 50,
      "zero_terms_query": "NONE",
      "auto_generate_synonyms_phrase_query": true,
      "fuzzy_transpositions": true,
      "boost": 1
    }
  }
}

说明:可以同时对多个任意字段进行分词查询

多字段词组分词查询

1.类比mysql
select * from user where name like "%liujjing hello %"
2.java api

/**
 * 单字段查询(模糊-词组分词查询)
 * @param searchDocDto
 */
public void search13(SearchDocDto searchDocDto) throws IOException {
    //构件match查询
    MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery(searchDocDto.getKey(), searchDocDto.getValue());

    //查询
    searchCommon(searchDocDto.getIndexName(),matchPhraseQueryBuilder);
}

3.elasticsearch

POST test-index-20220228/_search
{
  "query": {
    "match_phrase": {
      "name": {
        "query": "liujing2 hello",
        "slop": 0,
        "zero_terms_query": "NONE",
        "boost": 1
      }
    }
  }
}

说明:可以任意字段进行词语分词查询

范围和分页查询

单字段范围查询

1.类比mysql
select * from user where age >20 and age<30
2.java api

/**
 * 单字段查询(范围)
 * @param searchDocDto
 * @throws IOException
 */
public void search3(SearchDocDto searchDocDto) throws IOException {
    //构件查询
    RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(searchDocDto.getKey());
    rangeQueryBuilder.from(searchDocDto.getStartValue());
    rangeQueryBuilder.to(searchDocDto.getEndValue());

    //查询
    searchCommon(searchDocDto.getIndexName(),rangeQueryBuilder);
}

3.elasticsearch

POST test-index-20220228/_search
{
  "query": {
    "range": {
      "age": {
        "from": "2",
        "to": "19",
        "include_lower": true,
        "include_upper": true,
        "boost": 1
      }
    }
  }
}

说明: 可以进行任意单字段范围批量查询操作

分页查询

1.类比mysql
select * from user limit 1 5
2.java api

/**
 * 分页
 * @param searchDocDto
 */
public void search14(SearchDocDto searchDocDto) throws IOException {

    SearchRequest searchRequest = new SearchRequest(searchDocDto.getIndexName());
    //构建查询
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    //分页
    searchSourceBuilder.from(1);
    searchSourceBuilder.size(2);

    searchRequest.source(searchSourceBuilder);

    log.info("查询条件"+searchSourceBuilder.toString());

    SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

    SearchHits hits = search.getHits();

    for (SearchHit searchHit:hits){
        log.info(JSONUtil.toJsonStr(searchHit.getSourceAsString()));
    }
}

3.elasticsearch

POST test-index-20220228/_search
{
  //query  可以使用query分页
  
  "from": 1,
  "size": 5
}

说明: 可以进行带条件分页查询

复合条件查询

should

1.类比mysql
select * from user = "张三" or age=18
2.java api

/**
 * 复合多字段查询(should)
 * @param searchDocDto
 */
public void search4(SearchDocDto searchDocDto) throws IOException {
    //构件查询
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

    JSONObject query = searchDocDto.getQuery();
    Set<String> strings = query.keySet();

    for(String key:strings) {
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(key, query.get(key));
        boolQueryBuilder.should(termQueryBuilder);
    }
    //查询
    searchCommon(searchDocDto.getIndexName(),boolQueryBuilder);
}

3.elasticsearch

POST test-index-20220228/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "name": {
              "value": "liujing",
              "boost": 1
            }
          }
        },
        {
          "term": {
            "age": {
              "value": 19,
              "boost": 1
            }
          }
        }
      ],
      "adjust_pure_negative": true,
      "boost": 1
    }
  }
}

说明: 可以进行多字段进行or查询,只要满足一个shoud的条件即可

must

1.类比mysql
select * from user = "张三" and age=18
2.java api

/**
 * 复合多字段查询(must)
 * @param searchDocDto
 */
public void search5(SearchDocDto searchDocDto) throws IOException {
    //构件查询
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

    JSONObject query = searchDocDto.getQuery();
    Set<String> strings = query.keySet();

    for(String key:strings) {
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(key, query.get(key));
        boolQueryBuilder.must(termQueryBuilder);
    }

    //查询
    searchCommon(searchDocDto.getIndexName(),boolQueryBuilder);
}

3.elasticsearch

POST test-index-20220228/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "name": {
              "value": "liujing",
              "boost": 1
            }
          }
        },
        {
          "term": {
            "age": {
              "value": 19,
              "boost": 1
            }
          }
        }
      ],
      "adjust_pure_negative": true,
      "boost": 1
    }
  }
}

说明: 可以进行多字段进行and查询,要同时满足多个条件才返回

must not

1.类比mysql
select * from user != "张三" and age!=18
2.java api

/**
 * 复合多字段查询(must not,不计算相关性分数,和must查询到数据相反)
 * @param searchDocDto
 */
public void search6(SearchDocDto searchDocDto) throws IOException {
    //构件查询
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

    JSONObject query = searchDocDto.getQuery();
    Set<String> strings = query.keySet();

    for(String key:strings) {
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(key, query.get(key));
        boolQueryBuilder.mustNot(termQueryBuilder);
    }
    //查询
    searchCommon(searchDocDto.getIndexName(),boolQueryBuilder);
}

3.elasticsearch

{
  "query": {
    "bool": {
      "must_not": [
        {
          "term": {
            "name": {
              "value": "liujing",
              "boost": 1
            }
          }
        },
        {
          "term": {
            "age": {
              "value": 19,
              "boost": 1
            }
          }
        }
      ],
      "adjust_pure_negative": true,
      "boost": 1
    }
  }
}

说明: 可以进行多字段进行and查询,要同时不满足多个条件才返回

filter

1.类比mysql
select * from user = "张三" and age=18
2.java api

/**
 * 复合多字段查询(filter,不计算相关性分数,和must查询到数据相同)
 * @param searchDocDto
 */
public void search7(SearchDocDto searchDocDto) throws IOException {
    //构件查询
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

    JSONObject query = searchDocDto.getQuery();
    Set<String> strings = query.keySet();

    for(String key:strings) {
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(key, query.get(key));
        boolQueryBuilder.filter(termQueryBuilder);
    }
    //查询
    searchCommon(searchDocDto.getIndexName(),boolQueryBuilder);
}

3.elasticsearch

{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "name": {
              "value": "liujing",
              "boost": 1
            }
          }
        },
        {
          "term": {
            "age": {
              "value": 19,
              "boost": 1
            }
          }
        }
      ],
      "adjust_pure_negative": true,
      "boost": 1
    }
  }
}

说明: 和must效果一样,只是不做评分

should,must,must_not,filter复合

1.类比mysql
select * from ((user = "张三" and age=18) and (balance=1000 or balance=2000))
2.java api

/**
 * 复合多字段查询(should,must,must_not,filter进行复合)
 * @param searchDocDto
 */
public void search8(SearchDocDto searchDocDto) throws IOException {
    //构件查询
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

    //构件should条件
    JSONObject query = searchDocDto.getShouldQuery();
    Set<String> strings = query.keySet();

    for(String key:strings) {
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(key, query.get(key));
        boolQueryBuilder.should(termQueryBuilder);
    }
    //构件must条件
    JSONObject query1 = searchDocDto.getMustQuery();
    Set<String> strings1 = query1.keySet();

    for(String key:strings1) {
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(key, query1.get(key));
        boolQueryBuilder.must(termQueryBuilder);
    }
    //查询
    searchCommon(searchDocDto.getIndexName(),boolQueryBuilder);
}

3.elasticsearch

POST test-index-20220228/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "sex": {
              "value": "w",
              "boost": 1
            }
          }
        },
        {
          "term": {
            "name": {
              "value": "liujing2",
              "boost": 1
            }
          }
        }
      ],
      "should": [
        {
          "term": {
            "balance": {
              "value": 1200,
              "boost": 1
            }
          }
        },
        {
          "term": {
            "age": {
              "value": 5,
              "boost": 1
            }
          }
        }
      ],
      "adjust_pure_negative": true,
      "boost": 1
    }
  }
}

说明: should,must,filter,must not这些查询的条件都满足

should,must,must_not,filter 和 bool复合

1.类比mysql
select * from ((user = "张三" and age=18) and (balance=1000 or balance=2000)) or((....))
2.java api

/**
 * 复合多字段查询((should,must,must_not,filter)(bool)进行复合)
 * @param searchDocDto
 */
public void search9(SearchDocDto searchDocDto) throws IOException {
    //构件查询
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

    //构件should条件
    JSONObject query = searchDocDto.getShouldQuery();
    Set<String> strings = query.keySet();

    for(String key:strings) {
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(key, query.get(key));
        boolQueryBuilder.should(termQueryBuilder);
    }
    //构件内部bool
    BoolQueryBuilder boolQueryBuilder1 = QueryBuilders.boolQuery();
    JSONObject query1 = searchDocDto.getInnerBoolQuery();
    Set<String> strings1 = query1.keySet();
    for(String key:strings1) {
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(key, query1.get(key));
        boolQueryBuilder1.must(termQueryBuilder);
    }

    boolQueryBuilder.should(boolQueryBuilder1);
    //查询
    searchCommon(searchDocDto.getIndexName(),boolQueryBuilder);
}

3.elasticsearch

GET test-index-20220228/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "balance": {
              "value": 1200,
              "boost": 1
            }
          }
        },
        {
          "term": {
            "age": {
              "value": 5,
              "boost": 1
            }
          }
        },
        {
          "bool": {
            "must": [
              {
                "term": {
                  "balance": {
                    "value": "50",
                    "boost": 1
                  }
                }
              },
              {
                "term": {
                  "age": {
                    "value": 2,
                    "boost": 1
                  }
                }
              }
            ],
            "adjust_pure_negative": true,
            "boost": 1
          }
        }
      ],
      "adjust_pure_negative": true,
      "boost": 1
    }
  }
}

说明: should,must,filter,must not内部可以再次嵌套bool系列条件

should,must,must_not,filter内部可使用基本查询

1.类比mysql
select * from (name="张三" or (age>20 and age<30) or name like "%三%")
2.java api

/**
 * 复合多字段查询((should,must,must_not,filter)(term,much,range)进行复合)
 * @param searchDocDto
 */
public void search10(SearchDocDto searchDocDto) throws IOException {
    //构件range条件
    RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(searchDocDto.getKey());
    rangeQueryBuilder.from(searchDocDto.getStartValue());
    rangeQueryBuilder.to(searchDocDto.getEndValue());

    //构件should条件
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    boolQueryBuilder.should(rangeQueryBuilder);

    //查询
    searchCommon(searchDocDto.getIndexName(),boolQueryBuilder);
}

3.elasticsearch

GET test-index-20220228/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "range": {
            "name": {
              "from": "1",
              "to": "19",
              "include_lower": true,
              "include_upper": true,
              "boost": 1
            }
          }
        }
      ],
      "adjust_pure_negative": true,
      "boost": 1
    }
  }
}

说明: should,must,filter,must not内部可以使用基本查询(term,match,range)

聚合查询

常用聚合

1.类比mysql
select count(*) from user where age>20 group by name,age
2.java api

/**
 * 聚合(terms--统计文档数量)==(group(可以嵌套group,相当于多字段group)+count(*)聚合函数)
 * 聚合(max)==(max(*)聚合函数)
 * 聚合(min)==(min(*)聚合函数)
 * 聚合(avg)==(avg(*)聚合函数)
 * 聚合(sum)==(sum(*)聚合函数)
 * 聚合(top_hits)==保存聚合后记录
 * @param searchDocDto
 * @throws IOException
 */
public void search15(SearchDocDto searchDocDto) throws IOException {

    SearchRequest searchRequest = new SearchRequest(searchDocDto.getIndexName());
    //构建查询
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    //聚合
    TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg");
    //设置聚合字段
    ageAgg.field(searchDocDto.getAggField());
    //设置展示聚合分布的结果数量
    ageAgg.size(searchDocDto.getAggSize());
    //设置聚合结果文档数下限
    ageAgg.minDocCount(searchDocDto.getAggMinDocCount());
    //设置排序
    BucketOrder count = BucketOrder.count(true);
    ageAgg.order(count);

    //设置子聚合
    AggregatorFactories.Builder builder = AggregatorFactories.builder();
    //设置平均值聚合函数
    AvgAggregationBuilder balanceAvgAgg = AggregationBuilders.avg("balanceAvgAgg");
    balanceAvgAgg.field("balance2");
    builder.addAggregator(balanceAvgAgg);

    //设置最大值聚合函数
    MaxAggregationBuilder maxAgg = AggregationBuilders.max("balanceMaxAgg");
    maxAgg.field("balance2");
    builder.addAggregator(maxAgg);

    //设置最小值聚合函数
    MinAggregationBuilder minAgg = AggregationBuilders.min("balanceMinAgg");
    minAgg.field("balance2");
    builder.addAggregator(minAgg);

    //设置总数聚合函数
    SumAggregationBuilder sumAggregationBuilder = AggregationBuilders.sum("balanceSumAgg");
    sumAggregationBuilder.field("balance2");
    builder.addAggregator(sumAggregationBuilder);

    //设置聚合中各值对应记录
    TopHitsAggregationBuilder aggRecord = AggregationBuilders.topHits("aggRecord");
    aggRecord.size(1);
    builder.addAggregator(aggRecord);

    ageAgg.subAggregations(builder);

    searchSourceBuilder.aggregation(ageAgg);

    searchRequest.source(searchSourceBuilder);

    log.info("查询条件"+searchSourceBuilder.toString());

    SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

    //获取聚合结果
    Aggregations aggregations = search.getAggregations();

    for (Aggregation aggr:aggregations.asList()){
        ParsedLongTerms parsedLongTerms=(ParsedLongTerms)aggr;
        List<? extends Terms.Bucket> buckets = parsedLongTerms.getBuckets();
        for(Terms.Bucket bucket:buckets){
            log.info(JSONUtil.toJsonStr(bucket));
        }
    }
}

3.elasticsearch

GET test-index-20220228/_search
{
  "aggregations": {
    "ageAgg": {
      "terms": {
        "field": "age",
        "size": 10,
        "min_doc_count": 1,
        "shard_min_doc_count": 0,
        "show_term_doc_count_error": false,
        "order": [
          {
            "_count": "asc"
          },
          {
            "_key": "asc"
          }
        ]
      },
      "aggregations": {
        "balanceAvgAgg": {
          "avg": {
            "field": "balance2"
          }
        },
        "balanceMaxAgg": {
          "max": {
            "field": "balance2"
          }
        },
        "balanceMinAgg": {
          "min": {
            "field": "balance2"
          }
        },
        "balanceSumAgg": {
          "sum": {
            "field": "balance2"
          }
        },
        "aggRecord": {
          "top_hits": {
            "from": 0,
            "size": 1,
            "version": false,
            "seq_no_primary_term": false,
            "explain": false
          }
        }
      }
    }
  }
}

说明:
1.term聚合类型相当于group by可以用于分布数据,当然可以嵌套term,相当于根据多个字段分组

2.term聚合后得到的聚合结果会有基本的文档数量

3.max,min,sum,avg相当于一些计算聚合函数

常用聚合2(聚合条件过滤)

1.类比mysql
select count(*) count from user where age>20 group by name,age having count>1
2.java api

/**
 * 聚合(bucket_selector)==(having in)聚合函数)
 * @param searchDocDto
 * @throws IOException
 */
public void search17(SearchDocDto searchDocDto) throws IOException {

    SearchRequest searchRequest = new SearchRequest(searchDocDto.getIndexName());
    //构建查询
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    //聚合term聚合
    TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg");
    ageAgg.field(searchDocDto.getAggField());
    searchSourceBuilder.aggregation(ageAgg);

    //设置子聚合
    AggregatorFactories.Builder builder = AggregatorFactories.builder();
    //设置bucket_selector
    Map<String, String> bucketsPath = new HashMap<>();
    bucketsPath.put("count","_count");
    BucketSelectorPipelineAggregationBuilder pipelineAggregationBuilder = new BucketSelectorPipelineAggregationBuilder
            ("filterAgg",bucketsPath, Script.parse("params.count>1"));
    builder.addPipelineAggregator(pipelineAggregationBuilder);

    ageAgg.subAggregations(builder);

    searchRequest.source(searchSourceBuilder);

    log.info("查询条件"+searchSourceBuilder.toString());

    SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

    Aggregations aggregations = search.getAggregations();

    for (Aggregation aggr:aggregations.asList()){
        ParsedLongTerms parsedLongTerms=(ParsedLongTerms)aggr;
        List<? extends Terms.Bucket> buckets = parsedLongTerms.getBuckets();
        for(Terms.Bucket bucket:buckets){
            log.info(JSONUtil.toJsonStr(bucket));
        }
    }
}

3.elasticsearch

GET test-index-20220228/_search
{
  "aggregations": {
    "ageAgg": {
      "terms": {
        "field": "age",
        "size": 10,
        "min_doc_count": 1,
        "shard_min_doc_count": 0,
        "show_term_doc_count_error": false,
        "order": [
          {
            "_count": "desc"
          },
          {
            "_key": "asc"
          }
        ]
      },
      "aggregations": {
        "filterAgg": {
          "bucket_selector": {
            "buckets_path": {
              "count": "_count"
            },
            "script": {
              "source": "params.count>1",
              "lang": "painless"
            },
            "gap_policy": "skip"
          }
        }
      }
    }
  }
}

说明: bucket_selector类型聚合可以将上一级聚合桶进行条件过滤

评分(后续)

总结

1.有基本的 term,match,range查询
2.should,must,must not filter复合可以内部使用基本查询
3.should,must,must not filter内部可以组合bool实现更复杂的复合查询
4.aggregations实现分组和聚合函数计算