ElasticSearch(2)-RestHighLevelClient


RestHighLevelClient是項目中使用ES一定會使用到的類。而且官方文檔簡單易讀,非常推薦直接閱讀官方文檔。
https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-document-index.html?baymax=rec&rogue=rec-1&elektra=guide

ES的安裝和IK分詞器以及初步集成已經介紹。這里簡單介紹基本使用。

基本概念

RestHighLevelClient在官方的介紹中,說到這一種Restful的設計。具體的含義,還是不能明白,但是,簡單來說,就是把數據操作按照Http的概念規范進行設計的。
ES可以使用Postman操作和訪問數據,也得益於此。並且操作數據時,嚴格遵守了put\post\delete\get的規范,比如是否冪等這些概念。
RestHighLevelClient,在實際使用時,會發現,他和你使用postman沒有區別。更方便的是,它設計了函數式編程的操作,我們使用時,是非常非常方便的!

  • 首先要創建一個put\post\delete\get對應的request。當然,還封裝了更多功能的請求體,但本質上還是requst。
  • 其次就是向這個請求體中添加信息。保存,需要設置保存的文檔,索引。查詢,需要設置查詢的內容。這些我們使用postman時,都進行過操作,這里實際上是一樣的。
  • 最后就是執行了,相當於postman中的執行requst和接受返回值。
  • 當然,針對返回值,我們可以進行封裝,供業務使用。

配置ES地址:

es.host=192.168.147.132
es.port=9200
es.scheme=http

在使用時,直接注入RestHighLevelClient即可。

創建索引

    public void test(){
        //創建索引,也可同時創建多個,在后面加參數即可,自己看源碼
        CreateIndexRequest request = new CreateIndexRequest("test");
        CreateIndexResponse createIndexResponse=
                restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
    }

增加一條帖子

    public void saveDiscussPost(DiscussPost post){
	    //創建索引,這里使用了函數式編程,先指定索引,然后設置id,將帖子以Json存入,可以看到非常方便和清晰。
        IndexRequest request= new IndexRequest("discusspost")
                .id(String.valueOf(post.getId())).source(JSON.toJSONString(post), XContentType.JSON);
            
	   //執行並接受響應,這里的reponse的結構和我們在postman中看到的完全一樣,使用get就可以取出來!
            IndexResponse response = this.restHighLevelClient.index(request, RequestOptions.DEFAULT);
    }

批量增加bulkRequest

//創建BulkRequest
        BulkRequest bulkRequest=new BulkRequest();
//要保存查找出來的100條數據
        List<DiscussPost> list=discussMapper.selectDiscussPosts(0, 100);
        for (DiscussPost post: list) {
            bulkRequest.add(new IndexRequest("discusspost")
                    .id(String.valueOf(post.getId())).source(JSON.toJSONString(post), XContentType.JSON));
        }
//批量保存
       BulkResponse response=restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT);

這里刪除使用了查詢滿足條件的文檔刪除,因此屬於批處理。使用了bulk進行操作。

    public void deleteDiscussPost(DiscussPost post){
        DeleteByQueryRequest requestByQuery=new DeleteByQueryRequest("discusspost")
                .setQuery(new TermQueryBuilder("id", post.getId()));
        BulkByScrollResponse deleteResponse = restHighLevelClient.deleteByQuery(requestByQuery, RequestOptions.DEFAULT);
    }

查當然是重頭戲,ES和數據庫的區別在於查詢!倒序索引、內容匹配,分詞查詢,內容高亮,都是在這里涉及的!這里只能簡單的說明,用法很多,還要結合需求多多看文檔。

這個方法展示了當我們在搜索框輸入內容時,返回一個分頁的,關鍵詞高亮的帖子列表給前端展示的過程。

    public Map<String, Object> searchDiscussPost(String keyword, int current, int limit){
	//創建查詢請求
        SearchRequest request = new SearchRequest();

		//由於查詢比較復雜,需要單獨`使用`SearchSourceBuilder`類進行操作,而不是直接操作requst。
		//仍然使用函數式編程。
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
                .query(QueryBuilders.multiMatchQuery(keyword, "title", "content"))// 查詢關鍵詞,並指定查詢字段包括帖子中的"title"標題, "content"內容字段。
                .sort(SortBuilders.fieldSort("type").order(SortOrder.DESC))//排序,按帖子的類型、熱度、時間排序
                .sort(SortBuilders.fieldSort("score").order(SortOrder.DESC))
                .sort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
                .from(current)//分頁:from=(page-1)*size
                .size(limit)
				/*高亮
				1、HighlightBuilder().field指定要處理的高亮字段,preTags postTag指定高亮次的前后標記
				2、函數式編程,繼續指定其他要高亮處理的字段。
				*/
                .highlighter(
                        new HighlightBuilder().field("title").preTags("<em>").postTags("</em>")
                        .field(new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>"))
                );
				
		//綁定請求
        request.source(searchSourceBuilder);

       //執行,得到響應結果
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
 
      //response.getHits()得到查詢命中的數據
        SearchHits hits = response.getHits();

        //一定要記得處理沒查到數據的情況
        if (hits.getTotalHits().value <= 0) {
            return null;
        }

        List<DiscussPost> list = new ArrayList<>();
		//封裝返回數據-查到的帖子。其他的沒什么注意,注意的是高亮部分要單獨從HighlightField取
        for (SearchHit hit : hits) {
            DiscussPost post = new DiscussPost();

            String id = hit.getSourceAsMap().get("id").toString();
            post.setId(Integer.valueOf(id));

            String userId = hit.getSourceAsMap().get("userId").toString();
            post.setUserId(Integer.valueOf(userId));

//這里取到的時未高亮的數據
            String title = hit.getSourceAsMap().get("title").toString();
            post.setTitle(title);
            String content = hit.getSourceAsMap().get("content").toString();
            post.setContent(content);

            String status = hit.getSourceAsMap().get("status").toString();
            post.setStatus(Integer.valueOf(status));

            String createTime = hit.getSourceAsMap().get("createTime").toString();
            post.setCreateTime(new Date(Long.parseLong(createTime)));//valueOf

            String commentCount = hit.getSourceAsMap().get("commentCount").toString();
            post.setCommentCount(Integer.valueOf(commentCount));
            
			// 處理高亮顯示的結果
            HighlightField titleField = hit.getHighlightFields().get("title");
            if (titleField != null) {
                post.setTitle(titleField.getFragments()[0].toString());
            }

            HighlightField contentField = hit.getHighlightFields().get("content");
            if (contentField != null) {
                post.setContent(contentField.getFragments()[0].toString());
            }

            list.add(post);
        }

//封裝其他分頁所需數據
        Map<String,Object> map=new HashMap<>();
        map.put("posts",list);
        String hitsStr = response.getHits().getTotalHits().toString();
        map.put("hits",response.getHits().getTotalHits().toString().substring(0,hitsStr.indexOf(" ")));
        map.put("score",response.getHits().getMaxScore());

        return map;
    }

這是高亮部分HighlightField:
image

這里的em>並不起高亮的作用,具體還要再css文件中設置樣式:
image
如圖,顯示成功:
image


免責聲明!

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



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