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);
}
删
这里删除使用了查询满足条件的文档删除,因此属于批处理。使用了
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);
SearchHits hits = response.getHits();
//一定要记得处理没查到数据的情况
if (hits.getTotalHits().value <= 0) {
return null;
}
List<DiscussPost> list = new ArrayList<>();
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;
}