ElasticSearch 7.4的DSL查询——高级检索,复合检索,聚合检索

空搜索 ,返回集群索引中的所有文档
http://192.168.1.135:9200/_search/
    查询结果中的hits部分,total表示检索出的记录总数,还包含着查询的前十条记录

增删改查,复合查询

### 一、条件查询
http://192.168.1.135:9200/score-statistics-2019.10/_search/

查询mac为11010030333247333400f47c1cd5c200,且statisticsTypeCode为1012的记录

{
  "query": { 
    "bool": { 
      "must": 
      [
              { 
                "match": { "statisticsTypeCode":   "1012"        }
            },
            {
                "match":{"mac":"11010030333247333400f47c1cd5c200"}
            }
      ]
    }
  }
}
############# term 子句,筛选满足其中一个条件的集合
GET score-statistics-2019.10/_search
{
  "from":0,"size": 40, 
  "query": { 
    "bool": { 
      "must": 
      [
        {
          "match": {
            "statisticsTypeCode": "1017"
          }
        },
        {
          "terms": {
            "mac": [
              "110100303136473730001f2ea408548f",
              "test1"
              ]
          }
        }
      ]
    }
  }
}


##### compound query(复合查询)bool query、boosting query、constant_score query、dis_max query的区别

#########  1、bool query(多查询或复合查询的默认查询方式)

    用于组合多个叶子或复合查询子句的默认查询,包含must, should, must_not, or filter 。must和should子句将它们的分数组合在一起 - 匹配子句越多越好 - 而must_not和filter子句在过滤器上下文中执行。

  must:返回的文档必须满足must子句的条件,并且参与计算分值

  filter:返回的文档必须满足filter子句的条件。不参与计算分值

  must_not:返回的文档必须不满足must_not定义的条件。不参与评分。

  should:返回的文档可能满足should子句的条件。在一个Bool查询中,如果没有must或者filter,有一个或者多个should子句,那么只要满足一个就可以返回。minimum_should_match参数定义了至少满足几个子句。

    注1:评分计算

        bool 查询会为每个文档计算相关度评分 _score , 再将所有匹配的 must 和 should 语句的分数 _score 求和,最后除以 must 和 should 语句的总数。

        must_not 语句不会影响评分; 它的作用只是将不相关的文档排除。

    注2:控制精度

        所有 must 语句必须匹配,所有 must_not 语句都必须不匹配,但有多少 should 语句应该匹配呢? 默认情况下,没有 should 语句是必须匹配的,只有一个例外:那就是当没有 must 语句的时候,至少有一个 should 语句必须匹配。

        就像我们能控制 match 查询的精度 一样,我们可以通过 minimum_should_match 参数控制需要匹配的 should 语句的数量, 它既可以是一个绝对的数字,又可以是个百分比:

#########  2、boosting query

    提升查询可用于有效降级与给定查询匹配的结果。与bool查询中的“NOT”子句不同,这仍然会选择包含不良术语的文档,但会降低其总分。

#########  3、constant_score query
        含另一个查询但在过滤器上下文中执行的查询。所有匹配的文档都给出相同的“常量”_score

#########  4、dis_max query

    一个接受多个查询的查询,并返回与任何查询子句匹配的任何文档。虽然bool查询组合了所有匹配查询的分数,但dis_max查询使用单个最佳匹配查询子句的分数。

    一个查询,它生成由其子查询生成的文档的并集,并为每个文档评分由任何子查询生成的该文档的最大分数,以及任何其他匹配子查询的平局增量。

    当在具有不同增强因子的多个字段中搜索单词时,这非常有用(因此不能将字段等效地组合到单个搜索字段中)。我们希望主要分数是与最高提升相关联的分数,而不是字段分数的总和(如布尔查询所给出的)。如果查询是“albino elephant”,则这确保匹配一个字段的“albino”和匹配另一个的“elephant”获得比匹配两个字段的“albino”更高的分数。要获得此结果,请同时使用Boolean Query和DisjunctionMax Query:对于每个术语,DisjunctionMaxQuery在每个字段中搜索它,而将这些DisjunctionMaxQuery的集合组合成BooleanQuery。 

#########  5、function_score query

    使用函数修改主查询返回的分数,以考虑流行度、最近度、距离或使用脚本实现的自定义算法等因素。


### 二、分页查询 ( "from":0,"size": 40 )
GET score-statistics-2019.10/_search
{
  "from":10,"size": 40, 
  "query": { 
    "bool": { 
      "should": 
      [
              { 
                "match": { "statisticsTypeCode":   "1012"        }
            },
            {
                "match":{"mac":"110100303136473730001f2ea408548f"}
            }
      ]
    }
  }
}


### 三、,count计数
GET score-statistics-2019.10/_count
{
  "query": { 
    "bool": { 
      "must": 
      [
        {
          "match": {
            "statisticsTypeCode": "1017"
          }
        },
        {
          "terms": {
            "mac": [
              "110100303136473730001f2ea408548f",
              "test1"
              ]
          }
        }
      ]
    }
  }
}

聚合查询,值运算
https://www.cnblogs.com/pilihaotian/p/5845754.html

单值聚合 sum avg min max,Cardinality (求基数)
{
  "size": 0,
  "aggs": {
    "return_balance": {
      "sum": {
        "field": "balance"
      }
    }
  }
}
返回balance之和,其中size=0 表示不需要返回参与查询的文档
多值聚合
percentiles 求百分比

{
  "size": 0,
  "aggs": {
    "states": {
      "terms": {
        "field": "gender"
      },
      "aggs": {
        "banlances": {
          "percentile_ranks": {
            "field": "balance",
            "values": [
              20000,
            ]
          }
        }
      }
    }
  }


status统计
查看balance的统计情况:
{
  "size": 0,
  "aggs": {
    "balance_stats": {
      "stats": {
        "field": "balance"
      }
    }
  }
}

extended_stats 扩展统计
{
  "size": 0,
  "aggs": {
    "balance_stats": {
      "extended_stats": {
        "field": "balance"
      }
    }
  }
}


### 高级索引语法 高级检索语法:term, wildcard, prefix, fuzzy, range, query_string, text, missing

    term:严格匹配条件,所查询的字段内容要与填入查询框搜索值一致;

    wildcard:通配符查询,* 表示全匹配,? 表示单一匹配,etc: aaa* 或者 a?b;

    prefix:前缀匹配,搜索框如果输入aa,那么可能匹配到的字段值为 aab,aavb等;

    fuzzy min_similarity:弹性模糊匹配,有两个搜索框,第一个搜索框为搜索匹配值,会自动纠错,比如输入 ggjk,那么可能会匹配到ggjo,第二个框为最小相似度,采用的算法是Damerau-Levenshtein(最佳字符串对齐)算法,不建议填写这个框,我到发稿前也是被搞的头皮发麻,等我完全吃透再更新;

    fuzzy max_expansions :弹性模糊匹配,有两个搜索框,第一个搜索框为搜索匹配值,会自动纠错,比如输入gjk,那么可能会匹配到ggjo,第二个框是最大扩展匹配数,比如是1,那么ggjk只会随机模糊匹配到一种可能结果,即使它会出现2种或者更加多,也只会搜索一种;

    range:范围查询,gt为大于,gte为大于等于,lt小于,lte小于等于,所搜索的字段值在两个搜索框标识数值之间;

    query_string:字符片段查询,如果是数字,则严格匹配数字,如果是字符串,则按照自身或者分片词匹配;

    text:分片词查询,等确定后更新;

    missing:查询没有定义该字段或者该字段值为null的数据。


#######  Range Query
查询符合must条件而且timestamp在1571969062到1571969065之间的结果
GET score-statistics-2019.10/_search
{
  "from":0,"size": 40, 
  "query": { 
    "bool": { 
      "must": 
      [
        {
          "match": {
            "statisticsTypeCode": "1017"
          }
        },
        {
          "terms": {
            "mac": [
              "110100303136473730001f2ea408548f",
              "test1"
              ]
          }
        }
      ],
      "filter": {
        "range": {
          "timestamp": {
            "gte": 1571969062,
            "lte": 1571969065
          }
        }
      }
    }
  }
}

        gte:  大于或等于
    gt:   大于
    lte:  小于或等于
    lt:     小于
    boost:  设置查询的提升值,默认为1.0 (修改得分)

######### Elasticsearch排序  根据时间戳排序
https://www.elastic.co/guide/cn/elasticsearch/guide/current/_Sorting.html#_Sorting_on_Multivalue_Fields

ES中排序的分类
根据建模方法的不同,ES中排序分为以下几种,每种都有不同的排序写法和局限:

    嵌套文档-根据主文档字段排序
    嵌套文档-根据内嵌文档字段排序
    父子文档-查父文档-根据子文档排序
    父子文档-查子文档-根据父文档排序
    更复杂的情况,父子文档里又嵌套了文档,然后进行排序
    更更复杂情况,父子文档里又嵌套了文档,然后进行脚本字段排序
    更更更复杂情况,父子文档里又嵌套了文档,然后使用自定义脚本进行评分排序……

###按照字段的值排序编辑

    根据timestamp降序排序,这种排序不会不计算得分("_score" : null,),因为score并没有用于排序
    GET score-statistics-2019.10/_search
    {
      "from":0,"size": 40, 
      "query": { 
        "bool": { 
          "must": 
          [
            {
              "match": {
                "statisticsTypeCode": "1017"
              }
            },
            {
              "terms": {
                "mac": [
                  "110100303136473730001f2ea408548f",
                  "test1"
                  ]
              }
            }
          ]
        }
      }
      , "sort": [
        {
          "timestamp": {
            "order": "desc"
          }
        }
      ]
    }

多级排序
    假定我们想要结合使用 date 和 _score 进行查询,并且匹配的结果首先按照日期排序,然后按照相关性排序:

    GET /_search
    {
        "query" : {
            "bool" : {
                "must":   { "match": { "tweet": "manage text search" }},
                "filter" : { "term" : { "user_id" : 2 }}
            }
        },
        "sort": [
            { "date":   { "order": "desc" }},
            { "_score": { "order": "desc" }}
        ]
    }
多值字段排序

多值字段的排序编辑
    一种情形是字段有多个值的排序, 需要记住这些值并没有固有的顺序;一个多值的字段仅仅是多个值的包装,这时应该选择哪个进行排序呢?

    对于数字或日期,你可以将多值字段减为单值,这可以通过使用 min 、 max 、 avg 或是 sum 排序模式 。 例如你可以按照每个 date 字段中的最早日期进行排序,通过以下方法:

    "sort": {
        "dates": {
            "order": "asc",
            "mode":  "min"
        }
    }

#### 查询记录数  GET score-statistics-2019.10/_count这个api来查询
GET score-statistics-2019.10/_count
{
  "query": { 
    "bool": { 
      "must": 
      [
        {
          "match": {
            "statisticsTypeCode": "1017"
          }
        },
        {
          "terms": {
            "mac": [
              "110100303136473730001f2ea408548f",
              "test1"
              ]
          }
        }
      ]
    }
  }
}


复合查询的java实现

    public List queryByTagLogs(String logType, Map<String, Object> contextMap, Date startTime, Date endTime) {
        List list = new ArrayList();

        // 1.创建并设置SearchSourceBuilder对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        boolQueryBuilder.must(QueryBuilders.matchAllQuery());//查询所有 此处为匹配所有文档
        //elasticsearch 里默认的IK分词器是会将每一个中文都进行了分词的切割,所以你直接想查一整个词  加上.keyword
        boolQueryBuilder.must(QueryBuilders.termQuery("logType.keyword", logType));

        //时间范围的设定
        if (startTime != null && endTime != null){
            boolQueryBuilder.must(QueryBuilders.rangeQuery("operateAt").from(startTime)
                    .to(endTime));
        }

        //把其它参数加进去
        if (contextMap != null){
            contextMap.forEach((key, value) -> {S
                if (value != null && !"".equals(value)) {
                    boolQueryBuilder.must(QueryBuilders.matchPhraseQuery(key, value));//must相当于and
                }
            });
        }
        sourceBuilder.query(boolQueryBuilder);// 查询条件--->生成DSL查询语句
        sourceBuilder.from(0);// 第几页
        sourceBuilder.size(100);// 每页多少条数据
//        sourceBuilder.sort("id", SortOrder.ASC); // 设置排序规则
//        sourceBuilder.timeout(new TimeValue(2000));// 设置超时时间为2s

        // 2.创建并设置SearchRequest对象
        SearchRequest searchRequest = new SearchRequest(INDEX);
        searchRequest.types(TYPE); // 设置request要搜索的索引和类型
        searchRequest.source(sourceBuilder);// 设置SearchSourceBuilder查询属性
        try {
            SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);//查询
            SearchHits hits = search.getHits();
            for (SearchHit hit: hits
                 ) {
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                String operateAt = sourceAsMap.get("operateAt").toString();
                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
                long time = formatter.parse(operateAt).getTime();
                sourceAsMap.put("operateAt", time);

                list.add(sourceAsMap);
            }
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } catch (ParseException e) {
            log.error(e.getMessage(), e);           
        }
        return list;
    }


     public Object queryAdsOperateTime(String mac, Long startTimeStamp, Long endTimeStamp,Integer pageSize,Integer pageNum) throws IOException {
        SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder= QueryBuilders.boolQuery();

        boolQueryBuilder.must(QueryBuilders.matchQuery("statisticsTypeCode",CAR_ADS_EJECT.getStatisticsTypeCode()));

        if (StringUtil.isNotEmpty(mac)){
            boolQueryBuilder.must(QueryBuilders.matchQuery("mac",mac));
        }
        if (startTimeStamp!=0&&endTimeStamp!=0){
            boolQueryBuilder.must(QueryBuilders.rangeQuery("timestamp").from(startTimeStamp).to(endTimeStamp));
        }
        searchSourceBuilder.query(boolQueryBuilder);
        searchSourceBuilder.from((pageNum-1)*pageSize);

        searchSourceBuilder.size(pageSize);
        CountRequest countRequest=new CountRequest();
        countRequest.source(searchSourceBuilder);
        CountResponse countResponse=esFactory.getClient().count(countRequest,RequestOptions.DEFAULT);


       long ejecj=countResponse.getCount();
       long click=1;
       long close=1;
      /* esFactory.getClient().search();*/
        Map resultMap=new HashMap();
        resultMap.put("ejecj",ejecj);
        resultMap.put("click",click);
        resultMap.put("close",close);
        return new R<>(resultMap,"统计浮窗操作的次数,弹出、点击、关闭");
    }


    public Object queryAdsOperateTime(String mac, Long startTimeStamp, Long endTimeStamp) throws IOException {
        SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder= QueryBuilders.boolQuery();

        boolQueryBuilder.must(QueryBuilders.matchQuery("statisticsTypeCode",CAR_ADS_EJECT.getStatisticsTypeCode()));

        if (StringUtil.isNotEmpty(mac)){
            boolQueryBuilder.must(QueryBuilders.matchQuery("mac",mac));
        }
        if (startTimeStamp!=0&&endTimeStamp!=0){
            boolQueryBuilder.must(QueryBuilders.rangeQuery("timestamp").from(startTimeStamp).to(endTimeStamp));
        }
        searchSourceBuilder.query(boolQueryBuilder);
        CountRequest countRequest=new CountRequest();
        countRequest.source(searchSourceBuilder);
        CountResponse countResponse=esFactory.getClient().count(countRequest,RequestOptions.DEFAULT);


       long ejecj=countResponse.getCount();
       long click=1;
       long close=1;
      /* esFactory.getClient().search();*/
        Map resultMap=new HashMap();
        resultMap.put("ejecj",ejecj);
        resultMap.put("click",click);
        resultMap.put("close",close);
        return new R<>(resultMap,"统计浮窗操作的次数,弹出、点击、关闭");
    }

发布了117 篇原创文章 · 获赞 17 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/Jack__iT/article/details/103775173