ElasticSearch的各種查詢

term&terms查詢

term查詢

term的查詢是代表完全匹配,搜索之前不會對你的關(guān)鍵字進行分詞灰瞻,對你的關(guān)鍵字企業(yè)文檔分詞庫中去匹配內(nèi)容。

#term匹配查詢
POST /sms_logs_index/sms_logs_type/_search
{
  "from": 0,   #limit  from,size
  "size": 5,
  "query": {
    "term": {
      "province": {
        "value": "河北"
      }
    }
  }
}
##不會對term中所匹配的值進行分詞查詢
// java代碼實現(xiàn)方式
@Test
public void testQuery() throws IOException {
    //        1 創(chuàng)建Request對象
    SearchRequest request = new SearchRequest(index);
    request.types(type);
    //        2 指定查詢條件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.from(0);
    builder.size(5);
    builder.query(QueryBuilders.termQuery("province", "河北"));

    request.source(builder);
    //        3 執(zhí)行查詢
    RestHighLevelClient client = ESClient.getClient();
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    //        4  獲取到_source中的數(shù)據(jù)
    for (SearchHit hit : response.getHits().getHits()) {
        Map<String, Object> result = hit.getSourceAsMap();
        System.out.println(result);
    }
}

terms查詢

相當(dāng)于in查詢

terms: where province = 河北 or province = ? or province = ?

#terms 匹配查詢
POST /sms_logs_index/sms_logs_type/_search
{
  "from": 0,
  "size": 5,
  "query": {
    "terms": {
      "province": [
        "河北",
        "河南"
      ]
    }
  }
}
// java代碼 terms 查詢
@Test
public void test_terms() throws IOException {
    SearchRequest request = new SearchRequest(index);
    request.types(type);

    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.termsQuery("province","河北","河南"));

    request.source(builder);

    RestHighLevelClient client = ESClient.getClient();
    SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

    for (SearchHit hit : resp.getHits().getHits()){
        System.out.println(hit);
    }
}

match查詢

match查詢屬于高層查詢,它會根據(jù)你查詢字段類型不一樣屏鳍,采用不同的查詢方式

match查詢溉仑,實際底層就是多個term查詢挖函,將多個term查詢的結(jié)果進行了封裝

  • 查詢的如果是日期或者是數(shù)值的話,它會根據(jù)你的字符串查詢內(nèi)容轉(zhuǎn)換為日期或者是數(shù)值對等
  • 如果查詢的內(nèi)容是一個不可被分的內(nèi)容(keyword)浊竟,match查詢不會對你的查詢的關(guān)鍵字進行分詞
  • 如果查詢的內(nèi)容是一個可被分的內(nèi)容(text),match則會根據(jù)指定的查詢內(nèi)容按照一定的分詞規(guī)則去分詞進行查

match_all查詢

查詢?nèi)績?nèi)容怨喘,不指定任何查詢條件津畸。

POST /sms_logs_index/sms_logs_type/_search
{
  "query": {
    "match_all": {}
  }
}
@Test
public void test_match_all() throws IOException {
    // 創(chuàng)建Request  ,放入索引和類型
    SearchRequest request = new SearchRequest(index);
    request.types(type);
    builder.size(20); //es默認查詢結(jié)果只展示10條,這里可以指定展示的條數(shù)
    //指定查詢條件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.matchAllQuery());
    request.source(builder);
    // 執(zhí)行查詢
    RestHighLevelClient client = ESClient.getClient();
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    // 獲取查詢結(jié)果必怜,遍歷顯示
    for (SearchHit hit : response.getHits().getHits()){
        System.out.println(hit);
    }
}

match查詢

根據(jù)某個Field

POST /sms_logs_index/sms_logs_type/_search
{
  "query": {
    "match": {
      "smsContent": "打車"
    }
  }
}
@Test
public void test_match_field() throws IOException {
    SearchRequest request = new SearchRequest(index);
    request.types(type);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.matchQuery("smsContext","打車"));
    request.source(builder);
    RestHighLevelClient client = ESClient.getClient();
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    for (SearchHit hit : response.getHits().getHits()){
        System.out.println(hit);
    }

}

布爾match查詢

基于一個Filed匹配的內(nèi)容肉拓,采用and或者or的方式進行連接

# 布爾match查詢
POST /sms_logs_index/sms_logs_type/_search
{
  "query": {
    "match": {
      "smsContext": {
        "query": "打車 女士",
        "operator": "and"   #or
      }
    }
  }
}
@Test
public void test_match_boolean() throws IOException {
    SearchRequest request = new SearchRequest(index);
    request.types(type);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.matchQuery("smsContext","打車 女士").operator(Operator.AND));
    request.source(builder);
    RestHighLevelClient client = ESClient.getClient();
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    for (SearchHit hit : response.getHits().getHits()){
        System.out.println(hit);
    }
}

multi_match查詢

match針對一個field做檢索,multi_match針對多個field進行檢索梳庆,多個key對應(yīng)一個text

POST /sms_logs_index/sms_logs_type/_search
{
  "query": {
    "multi_match": {
      "query": "河北",  #指定text
      "fields": ["province","smsContext"] #指定field
    }
  }
}
// java 實現(xiàn) 
@Test
public void test_multi_match() throws IOException {
    SearchRequest request = new SearchRequest(index);
    request.types(type);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    // 查詢的文本內(nèi)容  字段1 字段2 字段3 暖途。掘剪。堪簿。。看政。
    builder.query(QueryBuilders.multiMatchQuery("河北", "province", "smsContext"));
    request.source(builder);
    RestHighLevelClient client = ESClient.getClient();
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    for (SearchHit hit : response.getHits().getHits()) {
        System.out.println(hit);
    }
}

其他查詢

ID查詢

# id查詢
GET /sms_logs_index/sms_logs_type/1
GET /索引名/type類型/id
public void test_multi_match() throws IOException {
    GetRequest request = new GetRequest(index,type,"1");
    RestHighLevelClient client = ESClient.getClient();
    GetResponse resp = client.get(request, RequestOptions.DEFAULT);
    System.out.println(resp.getSourceAsMap());
}

ids查詢

根據(jù)多個id進行查詢更米,類似MySql中的where Id in (id1,id2,id3….)

POST /sms_logs_index/sms_logs_type/_search
{
  "query": {
    "ids": {
      "values": [1,2,3]  #id值
    }
  }
}
//java代碼
@Test
public void test_query_ids() throws IOException {
    SearchRequest request = new SearchRequest(index);
    request.types(type);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.idsQuery().addIds("1","2","3"));
    request.source(builder);
    RestHighLevelClient client = ESClient.getClient();
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    for (SearchHit hit : response.getHits().getHits()){
        System.out.println(hit.getSourceAsMap());
    }

}

prefix查詢

前綴查詢欺栗,可以通過一個關(guān)鍵字去指定一個Field的前綴,從而查詢到指定的文檔

POST /sms_logs_index/sms_logs_type/_search
{
  "query": {
    "prefix": {
      "smsContext": {
        "value": "河"
      }
    }
  }
}
# 與 match查詢的不同在于征峦,prefix類似mysql中的模糊查詢迟几。而match的查詢類似于嚴(yán)格匹配查詢
# 針對不可分割詞
 @Test
public void test_query_prefix() throws IOException {
    SearchRequest request = new SearchRequest(index);
    request.types(type);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.prefixQuery("smsContext","河"));
    request.source(builder);
    RestHighLevelClient client = ESClient.getClient();
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    for (SearchHit hit : response.getHits().getHits()){
        System.out.println(hit.getSourceAsMap());
    }
}

fuzzy查詢

fuzzy查詢:模糊查詢,我們可以輸入一個字符的大概栏笆,ES就可以根據(jù)輸入的內(nèi)容大概去匹配一下結(jié)果瘤旨,eg.你可以存在一些錯別字

#fuzzy查詢
POST /sms_logs_index/sms_logs_type/_search
{
  "query": {
    "fuzzy": {
      "corpName": {
        "value": "盒馬生鮮",
        "prefix_length": 2  # 指定前幾個字符要嚴(yán)格匹配
      }
    }
  }
}
// 不穩(wěn)定,查詢字段差太多也可能查不到
// java 實現(xiàn)
    @Test
    public void test_query_fuzzy() throws IOException {
        SearchRequest request = new SearchRequest(index);
        request.types(type);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(QueryBuilders.fuzzyQuery("corpName","盒馬生鮮").prefixLength(2));
        request.source(builder);
        RestHighLevelClient client = ESClient.getClient();
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        for (SearchHit hit : response.getHits().getHits()){
            System.out.println(hit.getSourceAsMap());
        }
    }
 // .prefixLength() :指定前幾個字符嚴(yán)格匹配

wildcard查詢

通配查詢竖伯,與mysql中的like查詢是一樣的存哲,可以在查詢時,在字符串中指定通配符*和占位符七婴?

#wildcard查詢
POST /sms_logs_index/sms_logs_type/_search
{
  "query": {
    "wildcard": {
      "corpName": {
        "value": "*車"   # 可以使用*和祟偷?指定通配符和占位符
      }
    }
  }
}
# ?代表一個占位符
# ??代表兩個占位符
// java代碼
@Test
public void test_query_wildcard() throws IOException {
    SearchRequest request = new SearchRequest(index);
    request.types(type);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.wildcardQuery("corpName","*車"));
    request.source(builder);
    RestHighLevelClient client = ESClient.getClient();
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    for (SearchHit hit : response.getHits().getHits()){
        System.out.println(hit.getSourceAsMap());
    }
}

range查詢

范圍查詢,只針對數(shù)值類型打厘,對某一個Field進行大于或者小于的范圍指定

POST /sms_logs_index/sms_logs_type/_search
{
 "query": {
   "range": {
     "relyTotal": {
       "gte": 0,  
       "lte": 3
     }
   }
 }
}

# 查詢范圍:[gte,lte]
# 查詢范圍:(gt,lt)
//java代碼
@Test
public void test_query_range() throws IOException {
    SearchRequest request = new SearchRequest(index);
    request.types(type);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.rangeQuery("fee").lt(5).gt(2));
    request.source(builder);
    RestHighLevelClient client = ESClient.getClient();
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    for (SearchHit hit : response.getHits().getHits()){
        System.out.println(hit.getSourceAsMap());
    }
}

regexp查詢

正則查詢修肠,通過你編寫的正則表達式去匹配內(nèi)容

PS: prefix,fuzzy,wildcar和regexp查詢效率相對比較低,在對效率要求比較高時,避免去使用

POST /sms_logs_index/sms_logs_type/_search
{
  "query": {
    "regexp": {
      "moible": "109[0-8]{7}"  # 匹配的正則規(guī)則
    }
  }
}
//java 代碼
@Test
public void test_query_regexp() throws IOException {
    SearchRequest request = new SearchRequest(index);
    request.types(type);
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.regexpQuery("moible","106[0-9]{8}"));
    request.source(builder);
    RestHighLevelClient client = ESClient.getClient();
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    for (SearchHit hit : response.getHits().getHits()){
        System.out.println(hit.getSourceAsMap());
    }
}

深分頁Scroll

ES對from+size有限制户盯,from和size兩者之和不能超過1w

原理:

from+size  ES查詢數(shù)據(jù)的方式:
  1  先將用戶指定的關(guān)鍵詞進行分詞處理
 2  將分詞去詞庫中進行檢索嵌施,得到多個文檔的id
 3  去各個分片中拉去指定的數(shù)據(jù)   耗時
 4  根據(jù)數(shù)據(jù)的得分進行排序       耗時
 5  根據(jù)from的值,將查詢到的數(shù)據(jù)舍棄一部分
 6  返回查詢結(jié)果

Scroll+size    在ES中查詢方式
  1  先將用戶指定的關(guān)鍵詞進行分詞處理
 2  將分詞去詞庫中進行檢索莽鸭,得到多個文檔的id
 3  將文檔的id存放在一個ES的上下文中吗伤,ES內(nèi)存
  4  根據(jù)你指定給的size的個數(shù)去ES中檢索指定個數(shù)的數(shù)據(jù),拿完數(shù)據(jù)的文檔id,會從上下文中移除
 5  如果需要下一頁的數(shù)據(jù)硫眨,直接去ES的上下文中足淆,找后續(xù)內(nèi)容
  6  循環(huán)進行4.5操作

缺點,Scroll是從內(nèi)存中去拿去數(shù)據(jù)的,不適合做實時的查詢巧号,拿到的數(shù)據(jù)不是最新的

# 執(zhí)行scroll查詢族奢,返回第一頁數(shù)據(jù),并且將文檔id信息存放在ES的上下文中丹鸿,指定生存時間
POST /sms_logs_index/sms_logs_type/_search?scroll=1m
{
  "query": {
    "match_all": {}
  },
  "size": 2,
  "sort": [
    {
      "fee": {
        "order": "desc"
      }
    }
  ]
}
#查詢下一頁的數(shù)據(jù)
POST /_search/scroll
{
  "scroll_id": "DnF1ZXJ5VGhlbkZldGNoAwAAAAAAACSPFnJjV1pHbENVVGZHMmlQbHVZX1JGdmcAAAAAAAAkkBZyY1daR2xDVVRmRzJpUGx1WV9SRnZnAAAAAAAAJJEWcmNXWkdsQ1VUZkcyaVBsdVlfUkZ2Zw==",
  "scoll" :"1m"  #scorll信息的生存時間
}
#刪除scroll在ES中上下文的數(shù)據(jù)
DELETE /_search/scroll/scrill_id
//java代碼
@Test
public void test_query_scroll() throws IOException {
    //        1   創(chuàng)建SearchRequest
    SearchRequest request = new SearchRequest(index);
    request.types(type);
    //        2   指定scroll信息,生存時間
    request.scroll(TimeValue.timeValueMinutes(1L));
    //        3   指定查詢條件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.size(2);
    builder.sort("fee",SortOrder.DESC);
    builder.query(QueryBuilders.matchAllQuery());
    //        4 獲取返回結(jié)果scrollid ,source
    request.source(builder);
    RestHighLevelClient client = ESClient.getClient();
    SearchResponse response = client.search(request,RequestOptions.DEFAULT);
    String scrollId = response.getScrollId();
    System.out.println(scrollId);
    while(true){
        //       5  循環(huán)創(chuàng)建SearchScrollRequest
        SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
        // 6 指定scrollid生存時間
        scrollRequest.scroll(TimeValue.timeValueMinutes(1L));
        //        7 執(zhí)行查詢獲取返回結(jié)果
        SearchResponse scrollResp = client.scroll(scrollRequest, RequestOptions.DEFAULT);
        //        8.判斷是否得到數(shù)據(jù)越走,輸出
        if (scrollResp.getHits().getHits() != null && scrollResp.getHits().getHits().length > 0){
            System.out.println("=======下一頁的數(shù)據(jù)========");
            for (SearchHit hit : scrollResp.getHits().getHits()){
                System.out.println(hit.getSourceAsMap());
            }
        }else{
            //        9.判斷沒有查詢到數(shù)據(jù)-退出循環(huán)
            System.out.println("沒得");
            break;
        }
    }
    // 10  創(chuàng)建clearScrollRequest
    ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
    // 11 指定scrollid
    clearScrollRequest.addScrollId(scrollId);
    // 12  刪除
    client.clearScroll(clearScrollRequest,RequestOptions.DEFAULT);
}

delete-by-query

根據(jù)term,match 等查詢方式去刪除大量索引
PS:如果你要刪除的內(nèi)容,時index下的大部分數(shù)據(jù)靠欢,推薦創(chuàng)建一個新的index,然后把保留的文檔內(nèi)容廊敌,添加到全新的索引

#Delet-by-query 刪除
POST /sms-logs-index/sms-logs-type/_delete_by_query
{
   "query": {
    "range": {
      "fee": {
        "lt": 20
      }
    }
  }
}
public void deleteByQuery() throws IOException {
    // 1.創(chuàng)建DeleteByQueryRequest
    DeleteByQueryRequest request = new DeleteByQueryRequest(index);
    request.types(type);

    // 2.指定條件
    request.setQuery(QueryBuilders.rangeQuery("fee").lt(20));

    // 3.執(zhí)行
    BulkByScrollResponse response = client.deleteByQuery(request, RequestOptions.DEFAULT);

    // 4.輸出返回結(jié)果
    System.out.println(response.toString());
}

復(fù)合查詢

bool查詢

復(fù)合過濾器,將你的多個查詢條件 以一定的邏輯組合在一起掺涛,

  • must:所有條件組合在一起,表示 and 的意思
  • must_not:將must_not中的條件疼进,全部都不匹配薪缆,表示not的意思
  • should:所有條件用should 組合在一起,表示or 的意思
# 省是 晉城 或者 北京
# 運營商不能是聯(lián)通
# smsContent 包含 戰(zhàn)士 和 的
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "province": {
              "value": "晉城"
            }
          }
          
        },
         {
          "term": {
            "province": {
              "value": "北京"
            }
          }
          
        }
      ],
      "must_not": [
        {
          "term": {
            "operatorId": {
              "value": "2"
            }
          }
        }
      ],
      "must": [
        {
          "match": {
            "smsContent": "戰(zhàn)士"
          }
        },
        {
          "match": {
            "smsContent": "的"
          }
        }
      ]
    }
  }
}
public void  boolSearch() throws IOException {

    //  1.創(chuàng)建 searchRequest
    SearchRequest request = new SearchRequest(index);
    request.types(type);
    // 2.指定查詢條件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
    // #省是 晉城 或者北京
    boolQueryBuilder.should(QueryBuilders.termQuery("province","北京"));
    boolQueryBuilder.should(QueryBuilders.termQuery("province","晉城"));

    //# 運營商不能是聯(lián)通
    boolQueryBuilder.mustNot(QueryBuilders.termQuery("operatorId",2));

    //#smsContent 包含 戰(zhàn)士 和的
    boolQueryBuilder.must(QueryBuilders.matchQuery("smsContent","戰(zhàn)士"));
    boolQueryBuilder.must(QueryBuilders.matchQuery("smsContent","的"));

    builder.query(boolQueryBuilder);
    request.source(builder);
    //  3.執(zhí)行查詢
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    // 4.輸出結(jié)果
    for (SearchHit hit : response.getHits().getHits()) {
        System.out.println(hit.getSourceAsMap());
    }
}

boosting 查詢

boosting 查詢可以幫助我們?nèi)ビ绊懖樵兒蟮膕core

  • positive:只有匹配上positive 查詢的內(nèi)容伞广,才會被放到返回的結(jié)果集中
  • negative:如果匹配上了positive 也匹配上了negative, 就可以 降低這樣的文檔score.
  • negative_boost:指定系數(shù),必須小于1 0.5

關(guān)于查詢時拣帽,分數(shù)時如何計算的:

  • 搜索的關(guān)鍵字再文檔中出現(xiàn)的頻次越高,分數(shù)越高
  • 指定的文檔內(nèi)容越短嚼锄,分數(shù)越高减拭。
  • 我們再搜索時,指定的關(guān)鍵字也會被分詞区丑,這個被分詞的內(nèi)容拧粪,被分詞庫匹配的個數(shù)越多,分數(shù)就越高沧侥。
#boosting 查詢
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "boosting": {
      "positive": {
        "match": {
          "smsContent": "戰(zhàn)士"
        }
      }, 
      "negative": {
        "match": {
          "smsContent": "團隊"
        }
      },
      "negative_boost": 0.2
    }
  }
}
public void  boostSearch() throws IOException {

    //  1.創(chuàng)建 searchRequest
    SearchRequest request = new SearchRequest(index);
    request.types(type);
    // 2.指定查詢條件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    BoostingQueryBuilder boost = QueryBuilders.boostingQuery(
        QueryBuilders.matchQuery("smsContent", "戰(zhàn)士"),
        QueryBuilders.matchQuery("smsContent", "團隊")
    ).negativeBoost(0.2f);
    builder.query(boost);
    request.source(builder);
    //  3.執(zhí)行查詢
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    // 4.輸出結(jié)果
    for (SearchHit hit : response.getHits().getHits()) {
        System.out.println(hit.getSourceAsMap());
    }
}

filter 查詢

query 查詢:根據(jù)你的查詢條件可霎,去計算文檔的匹配度得到一個分數(shù),并根據(jù)分數(shù)排序宴杀,不會做緩存的癣朗。

filter 查詢:根據(jù)查詢條件去查詢文檔,不去計算分數(shù)旺罢,而且filter會對經(jīng)常被過濾的數(shù)據(jù)進行緩存旷余。

#filter 查詢
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "corpName": "海爾智家公司"
           }
        },
        {
          "range":{
            "fee":{
              "lte":50
            }
          }
        }
      ]
    }
  }
}
public void filter() throws IOException {

    // 1.searchRequest
    SearchRequest searchRequest = new SearchRequest(index);
    searchRequest.types(type);

    // 2.指定查詢條件
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
    boolBuilder.filter(QueryBuilders.termQuery("corpName","海爾智家公司"));
    boolBuilder.filter(QueryBuilders.rangeQuery("fee").gt(20));
    sourceBuilder.query(boolBuilder);
    searchRequest.source(sourceBuilder);

    //  3.執(zhí)行
    SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

    //  4. 輸出結(jié)果
    for (SearchHit hit : response.getHits().getHits()) {
        System.out.println(hit.getSourceAsMap());
        System.out.println(hit.getId()+"的分數(shù)是:"+hit.getScore());
    }
}

高亮查詢

高亮查詢就是用戶輸入的關(guān)鍵字,以一定特殊樣式展示給用戶扁达,讓用戶知道為什么這個結(jié)果被檢索出來
高亮展示的數(shù)據(jù)正卧,本身就是文檔中的一個field,單獨將field以highlight的形式返回給用戶
ES提供了一個highlight 屬性,他和query 同級別跪解。
frament_size: 指定高亮數(shù)據(jù)展示多少個字符回來
pre_tags:指定前綴標(biāo)簽<front color="red">
post_tags:指定后綴標(biāo)簽 </font>

#highlight 高亮查詢
POST /sms-logs-index/sms-logs-type/_search
{
  "query": {
    "match": {
      "smsContent": "團隊"
    }
  },
  "highlight": {
    "fields": {
      "smsContent":{}
    },
    "pre_tags":"<font color='red'>",
    "post_tags":"</font>",
    "fragment_size":10
  }
}
public void highLightQuery() throws IOException {
    // 1.創(chuàng)建request
    SearchRequest request = new SearchRequest(index);
    request.types(type);

    // 2.指定查詢條件穗酥,指定高亮
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.matchQuery("smsContent","團隊"));
    HighlightBuilder highlightBuilder = new HighlightBuilder();
    highlightBuilder.field("smsContent",10)
        .preTags("<font colr='red'>")
        .postTags("</font>");
    builder.highlighter(highlightBuilder);
    request.source(builder);

    // 3.執(zhí)行
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    //4. 輸出結(jié)果
    for (SearchHit hit : response.getHits().getHits()) {
        System.out.println(hit.getHighlightFields().get("smsContent"));
    }
}

聚合查詢

ES的聚合查詢和mysql 的聚合查詢類似,ES的聚合查詢相比mysql 要強大得多。ES提供的統(tǒng)計數(shù)據(jù)的方式多種多樣砾跃。

#ES 聚合查詢的RSTFul 語法
POST /index/type/_search
{
    "aggs":{
        "(名字)agg":{
            "agg_type":{
                "屬性":"值"
            }
        }
    }
}

去重計數(shù)聚合查詢

去重計數(shù)骏啰,cardinality 先將返回的文檔中的一個指定的field進行去重,統(tǒng)計一共有多少條

# 去重計數(shù) 查詢 province
POST /sms-logs-index/sms-logs-type/_search
{
  "aggs": {
    "provinceAgg": {
      "cardinality": {
        "field": "province"
      }
    }
  }
}
public void aggCardinalityC() throws IOException {

    // 1.創(chuàng)建request
    SearchRequest request = new SearchRequest(index);
    request.types(type);

    // 2. 指定使用聚合查詢方式
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.aggregation(AggregationBuilders.cardinality("provinceAgg").field("province"));
    request.source(builder);

    // 3.執(zhí)行查詢
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    // 4.輸出返回結(jié)果
    Cardinality agg = response.getAggregations().get("provinceAgg");
    System.out.println(agg.getValue());
}

范圍統(tǒng)計

統(tǒng)計一定范圍內(nèi)出現(xiàn)的文檔個數(shù)抽高,比如判耕,針對某一個field 的值再0100,100200,200~300 之間文檔出現(xiàn)的個數(shù)分別是多少
范圍統(tǒng)計 可以針對 普通的數(shù)值,針對時間類型翘骂,針對ip類型都可以響應(yīng)壁熄。
數(shù)值 rang
時間 date_rang
ip ip_rang

#針對數(shù)值方式的范圍統(tǒng)計  from 帶等于效果 ,to 不帶等于效果
POST /sms-logs-index/sms-logs-type/_search
{
  "aggs": {
    "agg": {
      "range": {
        "field": "fee",
        "ranges": [
          {
            "to": 30
          },
           {
            "from": 30,
            "to": 60
          },
          {
            "from": 60
          }
        ]
      }
    }
  }
}
#時間方式統(tǒng)計
POST /sms-logs-index/sms-logs-type/_search
{
  "aggs": {
    "agg": {
      "date_range": {
        "field": "sendDate",
        "format": "yyyy", 
        "ranges": [
          {
            "to": "2000"
          },{
            "from": "2000"
          }
        ]
      }
    }
  }
}
#ip 方式 范圍統(tǒng)計
POST /sms-logs-index/sms-logs-type/_search
{
  "aggs": {
    "agg": {
      "ip_range": {
        "field": "ipAddr",
        "ranges": [
          {
            "to": "127.0.0.8"
          },
          {
            "from": "127.0.0.8"
          }
        ]
      }
    }
  }
}
public void aggRang() throws IOException {
    // 1.創(chuàng)建request
    SearchRequest request = new SearchRequest(index);
    request.types(type);

    // 2. 指定使用聚合查詢方式
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.aggregation(AggregationBuilders.range("agg").field("fee")
                        .addUnboundedTo(30)
                        .addRange(30,60)
                        .addUnboundedFrom(60));
    request.source(builder);

    // 3.執(zhí)行查詢
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    // 4.輸出返回結(jié)果
    Range agg = response.getAggregations().get("agg");
    for (Range.Bucket bucket : agg.getBuckets()) {
        String key = bucket.getKeyAsString();
        Object from = bucket.getFrom();
        Object to = bucket.getTo();
        long docCount = bucket.getDocCount();
        System.out.println(String.format("key: %s ,from: %s ,to: %s ,docCount: %s",key,from,to,docCount));
    }
}

統(tǒng)計聚合

他可以幫你查詢指定field 的最大值碳竟,最小值草丧,平均值,平方和...
使用 extended_stats

#統(tǒng)計聚合查詢 extended_stats
POST /sms-logs-index/sms-logs-type/_search
{
  "aggs": {
    "agg": {
      "extended_stats": {
        "field": "fee"
      }
    }
  }
}
// java實現(xiàn)   
public void aggExtendedStats() throws IOException {
    // 1.創(chuàng)建request
    SearchRequest request = new SearchRequest(index);
    request.types(type);

    // 2. 指定使用聚合查詢方式
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.aggregation(AggregationBuilders.extendedStats("agg").field("fee"));
    request.source(builder);

    // 3.執(zhí)行查詢
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    // 4.輸出返回結(jié)果
    ExtendedStats extendedStats =  response.getAggregations().get("agg");
    System.out.println("最大值:"+extendedStats.getMaxAsString()+",最小值:"+extendedStats.getMinAsString());
}

其他聚合查詢 查看官方文檔

https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-aggregations-metrics-weight-avg-aggregation.html

地圖經(jīng)緯度搜索

#創(chuàng)建一個經(jīng)緯度索引,指定一個 name ,一個location
PUT /map
{
  "settings": {
    "number_of_shards": 5,
    "number_of_replicas": 1
  },
  "mappings": {
    "map":{
      "properties":{
        "name":{
          "type":"text"
        },
        "location":{
          "type":"geo_point"
        }
      }
    }
  }
}

#添加測試數(shù)據(jù)
PUT /map/map/1
{
  "name":"天安門",
  "location":{
    "lon": 116.403694,
    "lat":39.914492
  }
}

PUT /map/map/2
{
  "name":"百望山",
  "location":{
    "lon": 116.26284,
    "lat":40.036576
  }
}

PUT /map/map/3
{
  "name":"北京動物園",
  "location":{
    "lon": 116.347352,
    "lat":39.947468
  }
}

ES 的地圖檢索方式

geo_distance :直線距離檢索方式
geo_bounding_box: 以2個點確定一個矩形莹桅,獲取再矩形內(nèi)的數(shù)據(jù)
geo_polygon:以多個點昌执,確定一個多邊形,獲取多邊形的全部數(shù)據(jù)

基于RESTFul 實現(xiàn)地圖檢索

geo_distance

#geo_distance 
POST /map/map/_search
{
  "query": {
    "geo_distance":{
        #確定一個點
      "location":{
        "lon":116.434739,
        "lat":39.909843
      },
      #確定半徑
      "distance":20000,
      #指定形狀為圓形
      "distance_type":"arc"
    }
  }
}
#geo_bounding_box
POST /map/map/_search
{
  "query":{
    "geo_bounding_box":{
      "location":{
        "top_left":{
          "lon":116.327805,
          "lat":39.95499
        },
        "bottom_right":{
          "lon": 116.363162,
          "lat":39.938395
        }
      }
    }
  }
}
#geo_polygon
POST /map/map/_search
{
  "query":{
    "geo_polygon":{
      "location":{
          # 指定多個點確定 位置
       "points":[
         {
           "lon":116.220296,
           "lat":40.075013
         },
          {
           "lon":116.346777,
           "lat":40.044751
         },
         {
           "lon":116.236106,
           "lat":39.981533
         } 
        ]
      }
    }
  }
}

java 實現(xiàn) geo_polygon

public class GeoDemo {
    RestHighLevelClient client =  EsClient.getClient();
    String index = "map";
    String type="map";

    @Test
    public void  GeoPolygon() throws IOException {
        //  1.創(chuàng)建searchRequest
        SearchRequest request  = new SearchRequest(index);
        request.types(type);

        //  2.指定 檢索方式

        SearchSourceBuilder builder =  new SearchSourceBuilder();
        List<GeoPoint> points = new ArrayList<>();
        points.add(new GeoPoint(40.075013,116.220296));
        points.add(new GeoPoint(40.044751,116.346777));
        points.add(new GeoPoint(39.981533,116.236106));
        builder.query(QueryBuilders.geoPolygonQuery("location",points));
        request.source(builder);
        // 3.執(zhí)行
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 4.輸出結(jié)果
        for (SearchHit hit : response.getHits().getHits()) {
            System.out.println(hit.getSourceAsMap());
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末诈泼,一起剝皮案震驚了整個濱河市懂拾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌铐达,老刑警劉巖岖赋,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瓮孙,居然都是意外死亡唐断,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門杭抠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栗涂,“玉大人,你說我怎么就攤上這事祈争〗锍蹋” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵菩混,是天一觀的道長忿墅。 經(jīng)常有香客問我,道長沮峡,這世上最難降的妖魔是什么疚脐? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮邢疙,結(jié)果婚禮上棍弄,老公的妹妹穿的比我還像新娘望薄。我一直安慰自己,他們只是感情好呼畸,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布痕支。 她就那樣靜靜地躺著,像睡著了一般蛮原。 火紅的嫁衣襯著肌膚如雪卧须。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天儒陨,我揣著相機與錄音花嘶,去河邊找鬼。 笑死蹦漠,一個胖子當(dāng)著我的面吹牛椭员,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播笛园,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼隘击,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了喘沿?” 一聲冷哼從身側(cè)響起闸度,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤竭贩,失蹤者是張志新(化名)和其女友劉穎蚜印,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體留量,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡窄赋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了楼熄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片忆绰。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖可岂,靈堂內(nèi)的尸體忽然破棺而出错敢,到底是詐尸還是另有隱情,我是刑警寧澤缕粹,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布稚茅,位于F島的核電站,受9級特大地震影響平斩,放射性物質(zhì)發(fā)生泄漏亚享。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一绘面、第九天 我趴在偏房一處隱蔽的房頂上張望欺税。 院中可真熱鬧侈沪,春花似錦、人聲如沸晚凿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽晃虫。三九已至皆撩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間哲银,已是汗流浹背扛吞。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留荆责,地道東北人滥比。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像做院,于是被迫代替她去往敵國和親盲泛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359