zoukankan      html  css  js  c++  java
  • ElasticSearch High Level REST API【2】搜索查询

    如下为一段带有分页的简单搜索查询示例

    在search搜索中大部分的搜索条件添加都可通过设置SearchSourceBuilder来实现,然后将SearchSourceBuilder

    RestHighLevelClient client = ElasticClient.getRestHighLevelClient();
    SearchRequest searchRequest = new SearchRequest();
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy"));
    sourceBuilder.from(0);
    sourceBuilder.size(5);
    sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); //设置一个可选的超时,控制允许搜索的时间
    searchRequest.source(sourceBuilder);
    
    try {
        SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
        Long total = search.getHits().getTotalHits(); //获取匹配的总数量
        System.out.println("总记录数:" + total);
        for (SearchHit hit : search.getHits().getHits()) {
                  float score = hit.getScore(); //获得分数,即匹配度 
              String source = hit.getSourceAsString();
              System.out.println(source);
        }
    
    } catch (IOException e) {
        e.printStackTrace();
    }

    search查询的返回值为SearchResponse,调用SearchResponse的getHits()方法会获取SearchHits对象,然后再通过SearchHits的getHits()方法即返回一个SearchHit[]数组。

    遍历SearchHit[]数组获取每一个对象,通过hit.getScore()可获取分数,即搜索匹配度。通过hit.getSourceAsString()可得到对象的json字符串。

    备注:在上述查询中用到了termQuery查询,ES还提供了matchQuery查询,不同的查询需求中需要选择不同的查询,在此需要了解这两个查询的区别:

    • termQuery : term为不使用分词器查找,类似精确查找。
    • matchQuery : mactch为使用分词器进行查找,会查询到一些近似匹配的内容。

    SearchHit使用汇总

    要获取返回的内容,需要获得SearchHit,下面总结下SearchHit的一些使用:

    SearchHits hits = searchResponse.getHits();
    long totalHits = hits.getTotalHits(); //查询命中总数
    float maxScore = hits.getMaxScore(); //查询命中的最高分数
    //嵌套在SearchHits可以迭代获取单个搜索结果中
    SearchHit[] searchHits = hits.getHits();
    for (SearchHit hit : searchHits) {
        //使用SearchHit做一些事情
    }
    //通过SearchHit还可以获取 返回数据 的索引、类型、docId和得分等基本信息
    String index = hit.getIndex(); 
    String type = hit.getType();
    String id = hit.getId();
    float score = hit.getScore();
    //hit还可以以Json字符串或Map的形式返回数据
    String sourceAsString = hit.getSourceAsString();
    Map<String, Object> sourceAsMap = hit.getSourceAsMap();
    String documentTitle = (String) sourceAsMap.get("title");
    List<Object> users = (List<Object>) sourceAsMap.get("user");
    Map<String, Object> innerObject = (Map<String, Object>) sourceAsMap.get("innerObject");

    指定排序

    sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC)); //按分数(即匹配度)排序
    sourceBuilder.sort(new FieldSortBuilder("_uid").order(SortOrder.ASC)); //通过指定字段来排序

    排序有两种排序方式,第一通过ScoreSortBuilder实现按分数(即匹配度)排序

    第二种方式通过指定字段来排序,如上图所示通过“_uid”字段排序

    关闭检索

    有时候我们只想要知道到底匹配了多少条具体,但不关系具体每条记录的内容,这个时候我们可以选择关闭检索,不去查询每天数据的内容,可通过如下方式实现:

    sourceBuilder.fetchSource(false);

    关闭检索后,运行程序输出如下

    只返回了总记录数,遍历输出每条数据均为 null

    另外还可以通过sourceBuilder接受一个或多个数组,来控制要要返回哪些字段,排除哪些字段。具体实现如下,第一个数组参数为要接受的字段,第二个数组参数为要排除的内容:

    String[] includeFields = new String[] {"title", "user", "innerObject.*"};
    String[] excludeFields = new String[] {"_type"};
    sourceBuilder.fetchSource(includeFields, excludeFields);

    高亮显示

    通过向SearchSourceBuilder添加HighlightBuilder示例可添加高亮显示功能

    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    HighlightBuilder highlightBuilder = new HighlightBuilder(); 
    HighlightBuilder.Field highlightTitle = new HighlightBuilder.Field("title"); 
    highlightTitle.highlighterType("unified"); //字段高亮显示类型,默认用标签包裹高亮字词
    highlightBuilder.field(highlightTitle);
    searchSourceBuilder.highlighter(highlightBuilder);

    以上只是在查询中加入高亮显示的功能,那么我们如何在查询结果中获取呢,通过SearchHit的getHighlightFields()方法获取我们需要关键内容:

    SearchHits hits = searchResponse.getHits();
    for (SearchHit hit : hits.getHits()) {
        Map highlightFields = hit.getHighlightFields();
        HighlightField highlight = highlightFields.get("title"); 
        Text[] fragments = highlight.fragments();  
        String fragmentString = fragments[0].string();
    }

     聚合操作

    public void aggregation(){
           RestHighLevelClient client = elasticClient.getRestHighLevelClient();
           SearchRequest searchRequest = new SearchRequest();
           SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
           TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_sex")
                   .field("sex.keyword");   //若不加keyword,在text类型上进行聚合操作时会报错
           aggregation.subAggregation(AggregationBuilders.avg("avg_age")
                   .field("age"));  //avg_age 为子聚合名称,名称可随意
           searchSourceBuilder.aggregation(aggregation);
           searchRequest.source(searchSourceBuilder);
           SearchResponse searchResponse = null;
           try {
               searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
           } catch (IOException e) {
               e.printStackTrace();
           }
           Aggregations aggregations = searchResponse.getAggregations();
           Terms byCompanyAggregation = aggregations.get("by_sex");
           Terms.Bucket elasticBucket = byCompanyAggregation.getBucketByKey("女性");
           Avg averageAge = elasticBucket.getAggregations().get("avg_age");
           double avg = averageAge.getValue();
           System.out.println("女性平均年龄:"+avg);
    }
  • 相关阅读:
    Webfunny Js错误分析讲解
    Webfunny漏斗分析功能讲解
    Webfunny自定义埋点功能讲解
    Webfunny连线用户功能讲解
    Webfunny用户细查功能讲解
    C语言打印数字前补0
    github上新晋star3K的开源AI模型,包含情感分析等
    IT系统架构的演化
    微服务架构与SOA架构的区别与联系
    开源的分布式事务-Seata的设计原理
  • 原文地址:https://www.cnblogs.com/chentop/p/10296501.html
Copyright © 2011-2022 走看看