希望给同样遇见es的你带来帮助,也希望彼此有更多的讨论
版本选择6.4.3
1-Java 客户端的使用 (中)
自动补全
条件查询(高亮展示)
1-自动补全功能
- 自动补全,选择你想补全的字段,经过分词,后存储到es
private boolean updateSuggest(CometIndex cometIndex) {
//初始化一个analyze
AnalyzeRequest request = new AnalyzeRequest();
request.text(cometIndex.getTitle(), cometIndex.getAuthor());//对标题和作者 补全
request.analyzer("ik_smart");////需要和创建索引时候保持一致
try {
AnalyzeResponse response = client.indices().analyze(request, RequestOptions.DEFAULT);
List<AnalyzeResponse.AnalyzeToken> tokens = response.getTokens();
if (tokens == null) {
log.warn("Can not analyze token for comet:{}", cometIndex.getCometId());
return false;
}
List<CometSuggest> suggests = Lists.newArrayList();
for (AnalyzeResponse.AnalyzeToken token : tokens) {
//排序数字类型 & 小于 两个字符的分词结果
//ES里面的数字类型
if ("<NUM>".equals(token.getTerm()) || token.getTerm().length() < 2) {
continue;
}
CometSuggest cometSuggest = new CometSuggest();
cometSuggest.setInput(token.getTerm());
suggests.add(cometSuggest);
}
cometIndex.setSuggest(suggests);
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
- 获取自动补全的值
@Override
public List<String> suggest(String prefix) {
try {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
CompletionSuggestionBuilder completionSuggestionBuilder=SuggestBuilders.completionSuggestion("suggest").prefix(prefix).size(5);
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("search_autoComplete", completionSuggestionBuilder);
searchSourceBuilder.suggest(suggestBuilder);
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(CometIndexKey.INDEX_NAME);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
Suggest suggest = searchResponse.getSuggest();
//过滤避免重复
int maxSuggest=0;
Set<String> suggestSet=new HashSet<String>();
CompletionSuggestion completionSuggestion = suggest.getSuggestion("search_autoComplete");
for (CompletionSuggestion.Entry entry : completionSuggestion.getEntries()) {
if(entry.getOptions().isEmpty()){
continue;
}
for (CompletionSuggestion.Entry.Option option : entry) {
String suggestText = option.getText().string();
if(suggestSet.contains(suggestText)){
continue;
}
suggestSet.add(suggestText);
maxSuggest++;
}
if(maxSuggest>5){
break;
}
}
//返回补全的数据
List <String>stringList=Lists.newArrayList(suggestSet.toArray(new String[]{}));
return stringList;
}catch (Exception e){
e.printStackTrace();
log.error("suggest error");
return null;
}
}
2-条件查询(高亮展示)
@Override
public List<CometIndexVO> query(RentSearch rentSearch) {
try {
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//先过滤分类 ,是否选择了分类(文章,问题,电影介绍...)
if (StringUtils.isNoneBlank(rentSearch.getCategory())) {
boolQuery.filter(QueryBuilders.termQuery(CometIndexKey.CATEGORY, rentSearch.getCategory()));
}
//过滤日期范围
if (rentSearch.getStartTime() != null || rentSearch.getEndTime() != null) {
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(CometIndexKey.CREATE_TIME);
if (rentSearch.getStartTime() != null) {
rangeQueryBuilder.gte(rentSearch.getStartTime());
}
if (rentSearch.getEndTime() != null) {
rangeQueryBuilder.lte(rentSearch.getEndTime());
}
boolQuery.filter(rangeQueryBuilder);
}
//如果 所有的 内容都不包括keyword,是否返回符合其他条件的数据。
BoolQueryBuilder keyWordBoolQuery=QueryBuilders.boolQuery();
//进行检索(精确/分词) 标题 权重 高于其他
keyWordBoolQuery.should(
QueryBuilders.matchQuery(CometIndexKey.TITLE, rentSearch.getKeywords()).boost(2.0f)
);
keyWordBoolQuery.should(QueryBuilders.multiMatchQuery(rentSearch.getKeywords(),
CometIndexKey.DESCRIPTION,
CometIndexKey.CONTENT,
CometIndexKey.AUTHOR
));
boolQuery.must(keyWordBoolQuery);
//加入到builder
sourceBuilder.query(boolQuery);
//是否高亮
boolean isHighlight=rentSearch.isHighlight();
if(isHighlight){
//暂时标题高亮展示
HighlightBuilder highlightBuilder = new HighlightBuilder();
HighlightBuilder.Field highlightTitle =
new HighlightBuilder.Field(CometIndexKey.TITLE);
highlightTitle.highlighterType("unified");
highlightBuilder.field(highlightTitle);
sourceBuilder.highlighter(highlightBuilder);
}
//指定排序
sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));//得分
sourceBuilder.sort(new FieldSortBuilder(CometIndexKey.CREATE_TIME).order(SortOrder.DESC));//时间
//返回指定的字段(如果关联了 数据库 可以只返回id,然后 通过id 去查询其他信息)
/*sourceBuilder.fetchSource(new String[]{CometIndexKey.COMET_ID,CometIndexKey.TITLE}, null);*/
//分页
sourceBuilder.from(rentSearch.getStart());
sourceBuilder.size(rentSearch.getSize());
log.info("Builder:{}", sourceBuilder.toString());
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(CometIndexKey.INDEX_NAME);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
RestStatus status = searchResponse.status();
List<CometIndexVO> list = Lists.newArrayList();
if (status == RestStatus.OK) {
TimeValue took = searchResponse.getTook();
log.info("[请求花费的毫秒]:{},({}),{}", took, took.getMillis(), took.getSeconds());
SearchHits hits = searchResponse.getHits();
SearchHit[] searchHits = hits.getHits();
long totalRecord=hits.getTotalHits();
log.info("[请求返回总数]:{}",totalRecord);
CometIndexVO cometIndexVO = null;
for (SearchHit hit : searchHits) {
// do something with the SearchHit
//处理返回结果:如果数据和mysql或者其他数据库同步,可以只返回id,然后 其他信息从mysql查询。此处不引入mysql,所有所有内容从es中返回获取
cometIndexVO = new CometIndexVO();
convert(hit,cometIndexVO,isHighlight);
list.add(cometIndexVO);
}
return list;
} else {
log.warn("search status is not Ok");
return list;
}
} catch (IOException e) {
e.printStackTrace();
log.error("search error");
return null;
}
}
//转换数据
private void convert(SearchHit hit,CometIndexVO cometIndexVO,boolean isHighlight){
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
Long cometId = Longs.tryParse(String.valueOf(sourceAsMap.get(CometIndexKey.COMET_ID)));
String title = (String) sourceAsMap.get(CometIndexKey.TITLE);
String category = (String) sourceAsMap.get(CometIndexKey.CATEGORY);
String author = (String) sourceAsMap.get(CometIndexKey.AUTHOR);
String editor = (String) sourceAsMap.get(CometIndexKey.EDITOR);
String description = (String) sourceAsMap.get(CometIndexKey.DESCRIPTION);
String content = (String) sourceAsMap.get(CometIndexKey.CONTENT);
String createTime = (String) sourceAsMap.get(CometIndexKey.CREATE_TIME);
cometIndexVO.setCometId(cometId);
cometIndexVO.setCategory(category);
cometIndexVO.setAuthor(author);
cometIndexVO.setContent(content);
cometIndexVO.setEditor(editor);
cometIndexVO.setCreateTime(createTime);
cometIndexVO.setDescription(description);
cometIndexVO.setTitle(title);
//是否需要高亮展示(暂时只设置了title字段)
if(isHighlight){
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if(highlightFields!=null&&highlightFields.size()>0){
HighlightField highlight = highlightFields.get(CometIndexKey.TITLE);
Text[] fragments = highlight.fragments();
String fragmentString = fragments[0].string();
log.info("fragmentString:{}",fragmentString);
cometIndexVO.setTitle(fragmentString);
}
}
}
3-测试
@Test
public void testSuggest(){
List<String> list=searchService.suggest("西");
for(String s:list){
System.out.println(s);
}
}
@Test
public void testQuery(){
//构造查询条件
RentSearch rentSearch=new RentSearch();
rentSearch.setCategory("article");//种类
rentSearch.setKeywords("西游记");
rentSearch.setStart(0);
rentSearch.setSize(5);
rentSearch.setHighlight(true);//需要高亮展示
List<CometIndexVO>result= searchService.query(rentSearch);
for(CometIndexVO cometIndexVO:result){
System.out.println(cometIndexVO.toString());
}
}
- 完整代码后续整理完会提供github
点击查看更多内容
2人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦