ElaticSearch

ElaticSearch

1.索引基本操作

1.1 創(chuàng)建一個索引

#創(chuàng)建一個索引
PUT /person
{
  "settings": {
    "number_of_shards": 5,
    "number_of_replicas": 1
  }
}
#查看索引
GET /person

1.3 刪除索引

#刪除索引
DELETE /person

1.4 ES中Field可以指定的類型

#String:
    text:一般用于全文檢索。將當(dāng)前的field進行分詞
# keyword: 當(dāng)前的Field不可被分詞 
#
#
#
#

1.5 創(chuàng)建索引并指定數(shù)據(jù)結(jié)構(gòu)

——以創(chuàng)建小說為例子

PUT /book
{
  "settings": {
      #備份數(shù)
    "number_of_replicas": 1,
      #分片數(shù)
    "number_of_shards": 5
  },
    #指定數(shù)據(jù)結(jié)構(gòu)
  "mappings": {
    #指定類型 Type
    "novel": {
    # 文件存儲的Field屬性名
      "properties": {
        "name": {
          "type": "text",
          "analyzer": "ik_max_word",
    #   指定當(dāng)前的Field可以作為查詢的條件
          "index": true
        },
        "authoor": {
          "type": "keyword"
        },
        "onsale": {
          "type": "date",
          "format": "yyyy-MM-dd"
        }
      }
    }
  }
}

1.6 文檔的操作

  • <u>文檔在ES服務(wù)中的唯一標(biāo)志,_index, _type, _id 三個內(nèi)容為組合,來鎖定一個文檔,操作抑或是修改</u>

1.6.1 新建文檔

  • 自動生成id
PUT /book/novel
{
  "name": "西游記",
  "authoor": "劉明",
  "onsale": "2020-12-11"
}
  • 手動指定ID(更推薦)
PUT /book/novel/1
{
  "name": "三國演義",
  "authoor": "小明",
  "onsale": "2020-12-11"
}

1.6.2 修改文檔

  • <u>覆蓋式修改</u>

    POST /book/novel/1
    {
      "name": "三國演義",
      "authoor": "小明",
      "onsale": "2020-12-11"
    }
    
    
    
  • <u>doc修改方式(更推薦)</u>

    POST /book/novel/1/_update
    {
      "doc": {
        "name": "極品家丁"
      }
    }
    #先鎖定文檔,_update  修改需要的字段即可
    

1.6.3 刪除文檔

  • <u>刪庫跑路</u>

    DELETE /book/novel/1
    

2. java操作ElaticSearch

2.1 Java鏈接ES

1、創(chuàng)建Maven工程
    導(dǎo)入依賴
#  4個依賴
   1、1  elasticsearch
<!-- https://mvnrepository.com/artifact/org.elasticsearch/elasticsearch -->
<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>6.5.4</version>
</dependency>

   1、2  elasticsearch的高級API
<!-- https://mvnrepository.com/artifact/org.elasticsearch.client/elasticsearch-rest-high-level-client -->
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>6.5.4</version>
</dependency>

   1、3   junit
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

   1、4  lombok
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
    <scope>provided</scope>
</dependency>

2.1.2 創(chuàng)建測試類,連接ES

// 先創(chuàng)建連接,工具類
public class ESClient {

    public static RestHighLevelClient getClient(){
//        創(chuàng)建HttpHost對象
        HttpHost httpHost = new HttpHost("127.0.0.1",9200);
//      創(chuàng)建RestClientBuilder
        RestClientBuilder builder = RestClient.builder(httpHost);
        //      創(chuàng)建RestHighLevelClien對象
        RestHighLevelClient client = new RestHighLevelClient(builder);

        return client;
    }
}

2.2 java創(chuàng)建索引

import com.dengzhou.utils.ESClient;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.junit.jupiter.api.Test;

import java.io.IOException;

public class Create_ES_Index {
    String index = "person";
    String type = "man";
    @Test
    public void createIndex() throws IOException {
     //1、 準(zhǔn)備關(guān)于索引的settings
        Settings.Builder settings = Settings.builder()
                .put("number_of_shards", 3)
                .put("number_of_replicas", 1);


        //2、 準(zhǔn)備關(guān)于索引的結(jié)構(gòu)mappings
        XContentBuilder mappings = JsonXContent.contentBuilder()
                .startObject()
                    .startObject("properties")
                        .startObject("name")
                            .field("type","text")
                        .endObject()
                        .startObject("age")
                            .field("type","integer")
                        .endObject()
                        .startObject("birthday")
                             .field("type","date")
                             .field("format","yyyy-MM-dd")
                        .endObject()
                    .endObject()
                .endObject();

        //2 將settings 和 mappings封裝成一個request對象
        CreateIndexRequest request = new CreateIndexRequest(index)
                .settings(settings)
                .mapping(type,mappings);
        //3   通過client對象去鏈接es并執(zhí)行創(chuàng)建索引
        RestHighLevelClient client = ESClient.getClient();
        CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);

        //測試
        System.out.println("response"+response.toString());

    }

2.3 檢查索引是否存在,刪除索引

//檢查索引是否存在
    @Test
    public void exists() throws IOException {
        //1 準(zhǔn)備request對象
        GetIndexRequest request = new GetIndexRequest();
        request.indices(index);
        // 2 通過client去檢查
        RestHighLevelClient client = ESClient.getClient();
        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        System.out.println(exists);
    }

2.4 修改文檔

  • <u>添加文檔操作</u>

    @Test
        public void createDoc() throws IOException {
            ObjectMapper mapper = new ObjectMapper();
    
    //        1. 準(zhǔn)備json數(shù)據(jù)
            Person person = new Person(1, "張三", 23, new Date());
            String json = mapper.writeValueAsString(person);
            System.out.println(json);
    
    //        2. 準(zhǔn)備一個request對象(手動指定id創(chuàng)建)
            IndexRequest indexRequest = new IndexRequest(index,type,person.getId().toString());
            indexRequest.source(json, XContentType.JSON);
    
    //            3、通過client對象執(zhí)行添加操作
            RestHighLevelClient client = ESClient.getClient();
            IndexResponse resp = client.index(indexRequest, RequestOptions.DEFAULT);
    
    //            4、 輸出返回
            System.out.println(resp.getResult().toString());
        }
    
  • <u>修改文檔</u>

    //    修改文檔,通過doc方式
        @Test
        public void updateDoc() throws IOException {
    //        創(chuàng)建map,指定需要修改的內(nèi)容
            Map<String,Object> map = new HashMap<String, Object>();
            map.put("name","李四");
            String docId = "1";
    //           創(chuàng)建一個request對象,封裝數(shù)據(jù)
            UpdateRequest updateRequest = new UpdateRequest(index,type,docId);
            updateRequest.doc(map);
    //        通過client對象執(zhí)行
            RestHighLevelClient client = ESClient.getClient();
            UpdateResponse update = client.update(updateRequest, RequestOptions.DEFAULT);
    //                返回輸出結(jié)果
            System.out.println(update.getResult().toString());
        }
    

    2.5 刪除文檔

2.6 java批量操作文檔

  • 
    

3.ElasticSearch練習(xí)

  • <u>索引</u> : <u>sms-logs-index</u>

  • <u>類型:sms-logs-type</u>

字段名稱 備注
createDate 創(chuàng)建時間String
sendDate 發(fā)送時間 date
longCode 發(fā)送長號碼 如 16092389287811 string
Mobile 如 13000000000
corpName 發(fā)送公司名稱,需要分詞檢索
smsContent 下發(fā)短信內(nèi)容,需要分詞檢索
State 短信下發(fā)狀態(tài) 0 成功 1 失敗 integer
Operatorid 運營商編號1移動2聯(lián)通3電信 integer
Province 省份
ipAddr 下發(fā)服務(wù)器IP地址
replyTotal 短信狀態(tài)報告返回時長 integer
Fee 扣費 integer
  • 創(chuàng)建實例代碼

    //先定義索引名和類型名 
    String index = "sms_logs_index";
     String type = "sms_logs_type";
    
 public void create_index() throws IOException {
        Settings.Builder settings = Settings.builder()
                .put("number_of_shards", 3)
                .put("number_of_replicas", 1);

        XContentBuilder mappings = JsonXContent.contentBuilder()
                .startObject()
                    .startObject("properties")
                        .startObject("createDate")
                            .field("type", "text")
                        .endObject()
                        .startObject("sendDate")
                            .field("type", "date")
                            .field("format", "yyyy-MM-dd")
                        .endObject()
                        .startObject("longCode")
                            .field("type", "text")
                        .endObject()
                        .startObject("mobile")
                            .field("type", "text")
                        .endObject()
                        .startObject("corpName")
                            .field("type", "text")
                            .field("analyzer", "ik_max_word")
                        .endObject()
                        .startObject("smsContent")
                            .field("type", "text")
                            .field("analyzer", "ik_max_word")
                        .endObject()
                        .startObject("state")
                            .field("type", "integer")
                        .endObject()
                        .startObject("operatorid")
                            .field("type", "integer")
                        .endObject()
                        .startObject("province")
                            .field("type", "text")
                        .endObject()
                        .startObject("ipAddr")
                            .field("type", "text")
                        .endObject()
                        .startObject("replyTotal")
                            .field("type", "integer")
                        .endObject()
                        .startObject("fee")
                            .field("type", "integer")
                        .endObject()
                    .endObject()
                .endObject();

        CreateIndexRequest request = new CreateIndexRequest(index)
                .settings(settings)
                .mapping(type,mappings);

        RestHighLevelClient client = ESClient.getClient();
        CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
        System.out.println(response.toString());
    }

  • <u>數(shù)據(jù)導(dǎo)入部分</u>

    PUT /sms_logs_index/sms_logs_type/1
    {
      "corpName": "途虎養(yǎng)車",
      "createDate": "2020-1-22",
      "fee": 3,
      "ipAddr": "10.123.98.0",
      "longCode": 106900000009,
      "mobile": "1738989222222",
      "operatorid": 1,
      "province": "河北",
      "relyTotal": 10,
      "sendDate": "2020-2-22",
      "smsContext":   "【途虎養(yǎng)車】親愛的燈先生,您的愛車已經(jīng)購買",
      "state": 0
    }
    

4. ES的各種查詢

4.1 term&terms查詢

4.1.1 term查詢

  • <u>term的查詢是代表完全匹配,搜索之前不會對你的關(guān)鍵字進行分詞</u>
#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);
        }
    }
  • <u>terms是針對一個字段包含多個值得運用</u>

    • <u>terms: where province = 河北 or province = ? or province = ?</u>
    #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);
            }
        }
    

4.2 match查詢

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

<u>match查詢,實際底層就是多個term查詢,將多個term查詢的結(jié)果進行了封裝</u>

  • <u>查詢的如果是日期或者是數(shù)值的話,它會根據(jù)你的字符串查詢內(nèi)容轉(zhuǎn)換為日期或者是數(shù)值對等</u>

  • <u>如果查詢的內(nèi)容是一個不可被分的內(nèi)容(keyword),match查詢不會對你的查詢的關(guān)鍵字進行分詞</u>

  • <u>如果查詢的內(nèi)容是一個可被分的內(nèi)容(text),match則會根據(jù)指定的查詢內(nèi)容按照一定的分詞規(guī)則去分詞進行查詢</u>

4.2.1 match_all查詢

<u>查詢?nèi)績?nèi)容,不指定任何查詢條件</u>

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);
        }
    }

4.2.2 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);
        }

    }

4.2.3 布爾match查詢

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

# 布爾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);
        }

4.2.4 multi_match查詢

<u>match針對一個field做檢索,multi_match針對多個field進行檢索,多個key對應(yīng)一個text</u>

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);
        }
    }

4.3 ES 的其他查詢

4.3.1 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());
    }

4.3.2 ids查詢

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

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());
        }

    }

4.3.3 prefix查詢

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

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());
        }
    }

4.3.4 fuzzy查詢

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

#fuzzy查詢
#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)格匹配

4.3.5 wildcard查詢

<u>通配查詢,與mysql中的like查詢是一樣的,可以在查詢時,在字符串中指定通配符*和占位符?</u>

#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());
        }
    }

4.3.6 range查詢

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

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());
        }
    }

4.3.7 regexp查詢

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

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

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());
        }
    }

4.4 深分頁Scroll

<u>ES對from+size有限制,from和size兩者之和不能超過1w</u>

<u>原理:</u>

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操作

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

# 執(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);
    }

4.5 delete-by-query

<u>根據(jù)term,match等查詢方式去刪除大量的文檔</u>

<u>如果你需要刪除的內(nèi)容,是index下的大部分數(shù)據(jù),不建議使用,建議逆向操作,創(chuàng)建新的索引,添加需要保留的數(shù)據(jù)內(nèi)容</u>

POST /sms_logs_index/sms_logs_type/_delete_by_query
{
  "query": {
    "range": {
      "relyTotal": {
        "gte": 2,
        "lte": 3
      }
    }
  }
}

##中間跟你的查詢條件,查到什么,刪什么t
public class test_sms_search2 {
    String index = "sms_logs_index";
    String type = "sms_logs_type";
    @Test
    public void test_query_fuzzy() throws IOException {
        DeleteByQueryRequest request = new DeleteByQueryRequest(index);
        request.types(type);

        request.setQuery(QueryBuilders.rangeQuery("relyTotal").gt("2").lt("3"));

        RestHighLevelClient client = ESClient.getClient();
        BulkByScrollResponse response = client.deleteByQuery(request, RequestOptions.DEFAULT);

        System.out.println(response.toString());
    }
}

4.6 復(fù)合查詢

4.6. 1 bool查詢

<u>復(fù)合過濾器,可以將多個查詢條件以一定的邏輯組合在一起,and or</u>

  • must : <u>所有的條件,用must組合在一起,表示AND</u>

  • must_not:<u>將must_not中的條件,全部不能匹配,表示not的意思,不能匹配該查詢條件</u>

  • should: <u>所有條件,用should組合在一起,表示or的意思,文檔必須匹配一個或者多個查詢條件</u>

  • filter: <u>過濾器,文檔必須匹配該過濾條件,跟must子句的唯一區(qū)別是,filter不影響查詢的score</u>

#查詢省份為河北或者河南的
#并且公司名不是河馬生鮮的
#并且smsContext中包含軟件兩個字
POST /sms_logs_index/sms_logs_type/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "province": {
              "value": "河北"
            }
          }
        },
        {
          "term": {
            "province": {
              "value": "河南"
            }
           
        }
      ],
    "must_not": [
      {
        "term": {
          "corpName": {
            "value": "河馬生鮮"
          }
        }
      }
    ],
     "must": [
       {
         "match": {
           "smsContext": "軟件"
         }
       }
     ]
    }
  }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容