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