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,"統計浮窗操作的次數,彈出、點擊、關閉");
    }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章