ElasticSearch高級客戶端RestHighLevelClient


ElasticSearch高級客戶端RestHighLevelClient

記4個對象

1)導包

<!--引入es的坐標-->
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.4.0</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-client</artifactId>
    <version>7.4.0</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>7.4.0</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.4</version>
</dependency>

2)配置

#配置文件:聲明ES的主機、端口
heima:
  host: 192.168.200.128
  port: 9200
/*配置類:連接ES,生成RestHighLevelClient*/

3)代碼

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConfigurationProperties(prefix = "elasticsearch")
public class ElasticSearchConfig {
    private String host;
    private int port;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    @Bean
    public RestHighLevelClient client(){
        return new RestHighLevelClient(RestClient.builder(
                new HttpHost(
                        host,
                        port,
                        "http"
                )
        ));
    }
}

索引庫維護

索引庫維護:“索引庫、映射、文檔、域”增刪改

1)創建索引庫

public void addIndex() throws IOException {
    //1.使用client獲取操作索引的對象
    IndicesClient indicesClient = client.indices();
    //2.具體操作,獲取返回值
    CreateIndexRequest createRequest = new CreateIndexRequest("goods");
    CreateIndexResponse response = indicesClient.create(createRequest, RequestOptions.DEFAULT);

    //3.根據返回值判斷結果
    System.out.println(response.isAcknowledged());
}

2)創建映射

public void addIndexAndMapping() throws IOException {
    //1.使用client獲取操作索引的對象
    IndicesClient indicesClient = client.indices();
    //2.具體操作,獲取返回值
    CreateIndexRequest createRequest = new CreateIndexRequest("itcast");
    //2.1 設置mappings
    String mapping = "{\n" +
                "\t\"properties\": {\n" +
                "\t\t\"title\": {\n" +
                "\t\t\t\"type\": \"text\",\n" +
                "\t\t\t\"analyzer\": \"ik_smart\"\n" +
                "\t\t},\n" +
                "\t\t\"price\": { \n" +
                "\t\t\t\"type\": \"double\"\n" +
                "\t\t},\n" +
                "\t\t\"createTime\": {\n" +
                "\t\t\t\"type\": \"date\"\n" +
                "\t\t},\n" +
                "\t\t\"categoryName\": {\t\n" +
                "\t\t\t\"type\": \"keyword\"\n" +
                "\t\t},\n" +
                "\t\t\"brandName\": {\t\n" +
                "\t\t\t\"type\": \"keyword\"\n" +
                "\t\t},\n" +
                "\n" +
                "\t\t\"spec\": {\t\t\n" +
                "\t\t\t\"type\": \"object\"\n" +
                "\t\t},\n" +
                "\t\t\"saleNum\": {\t\n" +
                "\t\t\t\"type\": \"integer\"\n" +
                "\t\t},\n" +
                "\t\t\n" +
                "\t\t\"stock\": {\t\n" +
                "\t\t\t\"type\": \"integer\"\n" +
                "\t\t}\n" +
                "\t}\n" +
                "}";
    createRequest.mapping(mapping,XContentType.JSON);
    CreateIndexResponse response = indicesClient.create(createRequest, RequestOptions.DEFAULT);

    //3.根據返回值判斷結果
    System.out.println(response.isAcknowledged());
}
PUT goods
{
	"mappings": {
		"properties": {
			"title": {
				"type": "text",
				"analyzer": "ik_smart"
			},
			"price": { 
				"type": "double"
			},
			"createTime": {
				"type": "date"
			},
			"categoryName": {	
				"type": "keyword"
			},
			"brandName": {	
				"type": "keyword"
			},
	
			"spec": {		
				"type": "object"
			},
			"saleNum": {	
				"type": "integer"
			},
			
			"stock": {	
				"type": "integer"
			}
		}
	}
}

3)添加文檔

public void importData() throws IOException {
        //1.查詢所有數據,mysql
        List<Goods> goodsList = goodsMapper.findAll();
        //System.out.println(goodsList.size());
        //2.bulk導入
        BulkRequest bulkRequest = new BulkRequest();
        //2.1 循環goodsList,創建IndexRequest添加數據
        for (Goods goods : goodsList) {
            //2.2 設置spec規格信息 Map的數據   specStr:{}
            //goods.setSpec(JSON.parseObject(goods.getSpecStr(),Map.class));
            String specStr = goods.getSpecStr();
            //將json格式字符串轉為Map集合
            Map map = JSON.parseObject(specStr, Map.class);
            //設置spec map
            goods.setSpec(map);
            //將goods對象轉換為json字符串
            String data = JSON.toJSONString(goods);//map --> {}
            IndexRequest indexRequest = new IndexRequest("goods");
            indexRequest.id(goods.getId()+"").source(data, XContentType.JSON);
            bulkRequest.add(indexRequest);
        }
        BulkResponse response = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        System.out.println(response.status());
    }

高級操作

bulk批量操作

//作用:減少請求次數,提高效率
BulkRequest bulkRequest = new BulkRequest();
client.bulk(bulkRequest,RequestOptions.DEFAULT);
bulkRequest.add()

ES搜索

搜索套路代碼

public void search(Map searchMap) throws IOException {
    //1. 構建查詢請求對象,指定查詢的索引名稱
    SearchRequest searchRequest = new SearchRequest("goods");
    //2. 創建查詢條件構建器SearchSourceBuilder
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();//多條件拼接,布爾查詢構建器
   	//3. 封裝查詢條件、查詢方式
   	//3.1 基礎查詢(使用QueryBuilders構建的查詢對象),使用boolQueryBuilder封裝
    if(StringUtils.isNotBlank(searchMap.get("keyword"))){
        QueryBuilder keyword = QueryBuilders.matchQuery("title", searchMap.get("keyword"));
        boolQueryBuilder.filter(keyword);
    }
    ....
    //3.2 高級查詢(分頁,排序、分組、高亮)
    if(分頁判斷){
        
    }    
    sourceBuilder.from(curPage);
   	sourceBuilder.size(size);
    if(分組聚合判斷){//可以有多個;Aggregation:聚合
        AggregationBuilder agg1 = AggregationBuilders.terms("goods_brands").field("brandName").size(100);
        AggregationBuilder agg2 = AggregationBuilders.terms("goods_category").field("categoryName").size(100);
        ...
        sourceBulider.aggregation(agg1);
        sourceBulider.aggregation(agg2);
    }
    if(StringUtils.isNotBlank(searchMap.get("keyword"))){//高亮判斷
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        highlightBuilder.preTags("");
        highlightBuilder.postTags("");
        searchSourceBuilder.highlighter(highlightBuilder);
    }
    //4. 整合所有查詢條件
    searchSourceBuilder.query(boolQueryBuilder);   
    searchRequest.source(sourceBuilder);
    //5. 使用RestHighLevelClient執行搜索searchRequest
    SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
    //6. 獲取搜索結果
    SearchHits searchHits = searchResponse.getHits();
    //6.1 獲取總記錄數
    long value = searchHits.getTotalHits().value;
    System.out.println("總記錄數:"+value);
    List<Goods> goodsList = new ArrayList<>();
    //6.2 數據列表
    SearchHit[] hits = searchHits.getHits();
    for (SearchHit hit : hits) {
        //獲取json字符串格式的數據
        String sourceAsString = hit.getSourceAsString();
        //轉為java對象
        Goods goods = JSON.parseObject(sourceAsString, Goods.class);
        //6.3 高亮結果
        Map<String, HighlightField> highlightFields = hit.getHighlightFields();
        HighlightField HighlightField = highlightFields.get("title");
        Text[] fragments = HighlightField.fragments();
        //替換為“高亮內容”
        if(fragments != null && fragments.size() > 0){
            goods.setTitle(fragments[0].toString());
        }
        goodsList.add(goods);
    }
    //6.4 分組結果
    // 獲取聚合結果
    List brands = new ArrayList();
    Aggregations aggregations = searchResponse.getAggregations();
    Map<String, Aggregation> aggregationMap = aggregations.asMap();
    Terms goods_brands = (Terms) aggregationMap.get("goods_brands");
    List<? extends Terms.Bucket> buckets = goods_brands.getBuckets();
    for (Terms.Bucket bucket : buckets) {
        Object key = bucket.getKey();
        brands.add(key);
    }
    
}

ES支持的查詢方式

9用的多

QueryBuilders構建:
    1)match_all 查詢所有
        QueryBuilder query = QueryBuilders.matchAllQuery();//查詢所有文檔
    2)term 詞條查詢:不分詞,精確匹配
        QueryBuilder query = QueryBuilders.termQuery("title","華為");
    3)match 分詞查詢:先分詞,后查詢(分詞后默認使用"or"連接條件)
        QueryBuilder query = QueryBuilders.macthQuery("title", "華為手機");
    4) wildcard 模糊查詢
    	WildcardQueryBuilder query = QueryBuilders.wildcardQuery("title", "華*");
    5) regexp 正則查詢
    	 RegexpQueryBuilder query = QueryBuilders.regexpQuery("title", "\\w+(.)*");
    6) prefix 前綴查詢
    PrefixQueryBuilder query = QueryBuilders.prefixQuery("brandName", "三");
    7) range 范圍查詢
    	1)QueryBuilder query = QueryBuilders.rangeQuery("").gte("").lte("");
    	  //范圍查詢
        2)RangeQueryBuilder query = QueryBuilders.rangeQuery("price");
        //指定下限
       	query.gte(2000);
        //指定上限
        query.lte(3000);
    8) queryString 條件字符串查詢(作用:一值多域(輸入華為,在title和category等等有,都可查)查詢,支持分詞)
    QueryStringQueryBuilder query = QueryBuilders.queryStringQuery("華為手機").field("title").field("categoryName").field("brandName").defaultOperator(Operator.AND);
    queryStringQuery支持and和or的連接符;
    simplequeryStringQuery不支持
   	9) bool 布爾查詢,多條件拼接的條件構建器.連接的方式有下面4種-----》對8)多條件查詢的拼接
   		must:(and)必須滿足,計算分值
   		must_not:(not)必須不滿足,計算分值
   		should:(or)可以滿足,計算分值
   		---------------------------------
   		filter:必須滿足,不計算分值(效率高)
   		
   		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
   		
   		實例:
   		   /**
     * 9,布爾查詢:boolQuery
     *  1. 查詢品牌名稱為:華為
     *  2. 查詢標題包含:手機
     *  3. 查詢價格在:2000-3000
     */
    @Test
    public void testBoolQuery() throws IOException {


        SearchRequest searchRequest = new SearchRequest("goods");

        SearchSourceBuilder sourceBulider = new SearchSourceBuilder();


        //1.構建boolQuery
        BoolQueryBuilder query = QueryBuilders.boolQuery();

        //2.構建各個查詢條件
        //2.1 查詢品牌名稱為:華為
        QueryBuilder termQuery = QueryBuilders.termQuery("brandName","華為");
        query.must(termQuery);

        //2.2. 查詢標題包含:手機
        QueryBuilder matchQuery = QueryBuilders.matchQuery("title","手機");
        query.filter(matchQuery);

        //2.3 查詢價格在:2000-3000;gte大於等於;lte小於等於
        QueryBuilder rangeQuery = QueryBuilders.rangeQuery("price");
        ((RangeQueryBuilder) rangeQuery).gte(2000);
        ((RangeQueryBuilder) rangeQuery).lte(3000);
        query.filter(rangeQuery);

        //3.使用boolQuery連接

        sourceBulider.query(query);



        searchRequest.source(sourceBulider);


        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);


        SearchHits searchHits = searchResponse.getHits();
        //獲取記錄數
        long value = searchHits.getTotalHits().value;
        System.out.println("總記錄數:"+value);

        List<Goods> goodsList = new ArrayList<>();
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();

            //轉為java
            Goods goods = JSON.parseObject(sourceAsString, Goods.class);

            goodsList.add(goods);
        }

        for (Goods goods : goodsList) {
            System.out.println(goods);
        }
    }


SearchSourceBuilder構建:
	1)分頁
		searchSourceBuilder.from(0)
        searchSourceBuilder.size(10)
	2)排序
		searchSourceBuilder.sort(“field”,SortOrder.DESC|SortOrder.ASC);
	3)高亮(指定高亮域、設置高亮前綴、后綴)
	4)分組聚合
		(指標聚合(max,min,avg,sum)和桶聚合(groupby),桶聚合不能對text類型的使用:例:搜索面板上的品牌)
		  AggregationBuilder agg = AggregationBuilders.terms("goods_brands").field("brandName").size(100);//goods_brands是自己起的名字,brandName桶聚合的字段
        sourceBulider.aggregation(agg);



高亮的代碼操作
  /**
     *
     * 11,高亮查詢:
     *      1. 設置高亮
     *          * 高亮字段
     *          * 前綴
     *          * 后綴
     *      2. 將高亮了的字段數據,替換原有數據
     */
    @Test
    public void testHighLightQuery() throws IOException {


        SearchRequest searchRequest = new SearchRequest("goods");

        SearchSourceBuilder sourceBulider = new SearchSourceBuilder();

        // 1. 查詢title包含手機的數據
        MatchQueryBuilder query = QueryBuilders.matchQuery("title", "手機");

        sourceBulider.query(query);

        //設置高亮
        HighlightBuilder highlighter = new HighlightBuilder();
        //設置三要素(前后綴有默認的<em></em>)
        highlighter.field("title");
        highlighter.preTags("<font color='red'>");
        highlighter.postTags("</font>");


        sourceBulider.highlighter(highlighter);



        // 2. 查詢品牌列表
        /*
        參數:
            1. 自定義的名稱,將來用於獲取數據
            2. 分組的字段
         */
        AggregationBuilder agg = AggregationBuilders.terms("goods_brands").field("brandName").size(100);
        sourceBulider.aggregation(agg);



        searchRequest.source(sourceBulider);


        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);


        SearchHits searchHits = searchResponse.getHits();
        //獲取記錄數
        long value = searchHits.getTotalHits().value;
        System.out.println("總記錄數:"+value);

        List<Goods> goodsList = new ArrayList<>();
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();

            //轉為java
            Goods goods = JSON.parseObject(sourceAsString, Goods.class);

            // 獲取高亮結果,替換goods中的title
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField HighlightField = highlightFields.get("title");
            Text[] fragments = HighlightField.fragments();//高亮片段(現在只有一個:是數組的第一個元素);域可能是多值得,所以返回的數組
            //替換
            goods.setTitle(fragments[0].toString());


            goodsList.add(goods);
        }

        for (Goods goods : goodsList) {
            System.out.println(goods);
        }

        // 獲取聚合結果
        Aggregations aggregations = searchResponse.getAggregations();

        Map<String, Aggregation> aggregationMap = aggregations.asMap();

        //System.out.println(aggregationMap);
        Terms goods_brands = (Terms) aggregationMap.get("goods_brands");

        List<? extends Terms.Bucket> buckets = goods_brands.getBuckets();

        List brands = new ArrayList();
        for (Terms.Bucket bucket : buckets) {
            Object key = bucket.getKey();
            brands.add(key);
        }

        for (Object brand : brands) {
            System.out.println(brand);
        }

    }




SpringBoot整合ElasticSearch

1)導包

2)配置

3)代碼

ElasticSearch擴展

集群:把一個項目拆分成多個功能模塊,一個功能模塊代碼,部署到多台服務器,所有服務器完成相同的功能
	作用:高可用、負載均衡
分布式:把一個項目拆分成多個功能模塊,每個功能模塊單獨部署到一台服務器,協同完成一個流程
	作用:分擔存儲、計算壓力,提升應用響應速度
集群、分布式都是高並發解決方案。

ES集群中相關概念

集群-->(多個)節點(主節點、從節點)-->索引-->主分片、副分片
ES集群自平衡:
	集群中某個節點宕機,把該節點的分片,平衡到其他分片;當宕機服務器重啟啟動后,再對分片進行自平衡,把分片
	拷貝到新啟動的節點。
ES集群分片參考數據(僅供參考):
	分片總數 = 總數據量 / 10G-30G
	節點數 = 分片總數 / 1-3	
腦裂(普遍集群存在的問題):
	概念:在集群中,從節點在選擇主節點時,發生意見分歧,產生了多個主節點
	原因:
		1)網絡延遲
		2)主節點負載過大,節點假死
		3)JVM內存回收,節點假死
	解決:
		1) 使用內網
		2) ES-主節點專注負責管理,不處理其他請求
		3) ES-JVM內存設置為服務器內存的一半大小

1)索引庫維護

(1)准備數據;
(2)創建索引庫、映射、導入數據;

2)搜索

-------QueryBuilders.-----------
1)term
2)match
3)range
4)bool
-------SearchSourceBuilder-----------
5)page
6)sort
7)highlight
8)aggregation


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM