为了账号安全,请及时绑定邮箱和手机立即绑定

ElasticSearch 遇见(3)

标签:
Java
希望给同样遇见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人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消