Elasticsearch5.6如何让一个字段同时支持精确匹配和模糊检索

需求:如何让ES的某个字段既能支持精确匹配查找,也能支持模糊检索?
方法:将字段的mapping设置为如下这种即可:

"properties": {
               "name": {
                  "type": "text",
                  "fields": {
                     "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                     }
                  }
               }

举个栗子

"properties": {
               "name": {
                 "analyzer": "ik_max_word",
				"store": true,
				"type": "text"
               }

上面这种配置:它只能分词匹配,做不到精确匹配。如我有两条数据
数据1:也无风雨也无晴
数据2:也无风雨也无晴2
搜索:业务风雨也无晴2
正确的结果是只返回数据2,但事实是两条数据它都返回了

怎么样才能让它只返回数据2呢?

再举个栗子

"properties": {
               "name": {
                  "type": "text",
                  "fields": {
                     "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                     }
                  }
               }

上面这种配置,在搜索业务风雨也无晴2的时候将只返回数据2,于是我们就 让字段同时支持精确匹配和模糊检索了。

如果索引已经添加,要更改字段类型映射请看这篇文章,不用写代码,直接postmain就可以了
https://blog.csdn.net/java_xxxx/article/details/108710260

java代码

如果java代码中对字符串按MultiMatchQueryBuilder的方式搜索,并且再添加进入boolTrem里,可以精确匹配,如搜索:“也无风雨也无晴”,结果:“也无风雨也无晴”、“也无风雨也无晴2”、“也啊无啊风啊雨啊也啊无啊晴2”
如果搜索"也无风雨也无晴2",结果:“也无风雨也无晴2”、“也啊无啊风啊雨啊也啊无啊晴2”

如果使用matchPhraseQuery,前提是索引不分词,搜索结果会比上面少了一个““也啊无啊风啊雨啊也啊无啊晴2””,达到精确匹配的效果

postFilterKeyword.should(QueryBuilders.matchPhraseQuery(fileNmae, item));
 MultiMatchQueryBuilder query = QueryBuilders.multiMatchQuery(item, locations).type(MultiMatchQueryBuilder.Type.PHRASE).slop(50);
                        postFilterKeyword.should(query);
 public static Page listArticleByEs(Page page, ArticlePub filter){
        Integer pageSize = page.getPageSize();
        Integer pageNumber = page.getPageNumber();
        Short status = filter.getArticleStatus();
        Short articleType = filter.getArticleType();
        String columnIds = filter.getColumnIds();
        Integer roleId = filter.getRoleId();
        Integer userType = filter.getUserType();
        Long siteId = filter.getArticleSiteId();
        Date beginTime = filter.getBeginTime();
        Date endTime = filter.getEndTime();
        String location = filter.getLocation();
        Integer timeType = null == filter.getTimeType() ? 1 : filter.getTimeType();
        Integer articleRefNum = filter.getArticleRefNum();
        String keyWord = StringUtils.isBlank(filter.getKeyWord()) ? filter.getArticleTitle() : filter.getKeyWord();

        pageNumber = null == pageNumber ? 1 : pageNumber;
        pageSize = null == pageSize ? 20 : pageSize;
        
        TransportClient client = ESUtils.getClient();
        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(ESUtils.articleIndex).setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                .setTypes("article")
                .setFrom((pageNumber - 1) * pageSize).setSize(pageSize);
        // 时间查询
        if(null != beginTime && null != endTime){
            String fileName = timeType.equals(1) ? "sysCreateTime" : "sysModifyTime";
            searchRequestBuilder.setPostFilter(QueryBuilders.rangeQuery(fileName).from(dateFormat(beginTime)).to(dateFormat(endTime)).includeLower(true).includeUpper(true));
        }

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        BoolQueryBuilder postFilter = QueryBuilders.boolQuery();
        // 文章状态
        if (null != status) {
            postFilter.must(termQuery("articleStatus", status));
        }
        // 文章类型
        if (null != articleType) {
            postFilter.must(termQuery("articleType", articleType));
        }
        // 是否选用
        if (null != articleRefNum && articleRefNum == -2) {
            postFilter.must(rangeQuery("articleRefNum").gte(1));// 已选用
        } else if (null != articleRefNum && articleRefNum == -1) {
            postFilter.must(rangeQuery("articleRefNum").lt(1)); // 未选用
        }
        // 栏目过滤
        if (!StringUtils.isBlank(columnIds)) {
            // 字符串得到id集合
            List<Integer> cids = str2List(columnIds);
            postFilter.must(termsQuery("articleColumnId", cids));
        } else {
            if (userType.equals(1)) { // 站点管理员
                postFilter.must(termQuery("articleSiteId", siteId));
            } else {
                // 站点下有权限的所有栏目
                List<Integer> cids = getColumnIdsBySiteId(roleId);
                postFilter.must(termsQuery("articleColumnId", cids));
            }
        }
        // 未删除的文章
        postFilter.must(termQuery("sysDeleteFlag", 0));

        // 关键词查询
        String [] locations = handleLocation(location);
        if(!StringUtils.isBlank(keyWord)) {
            // 多个关键词以|分开表示or
            if (keyWord.indexOf("|") != -1) {
                BoolQueryBuilder postFilterKeyword = QueryBuilders.boolQuery();
                String[] split = keyWord.split("\\|");
                for (String item : split) {
                    if (!StringUtils.isBlank(item)) {
                        // 查询位置:locations:[articleTitle, articleContetn]
                        for (String fileNmae : locations) {
                            postFilterKeyword.should(QueryBuilders.matchPhraseQuery(fileNmae, item));
                        }
                    }
                }
                postFilter.must(postFilterKeyword);
            }  else if (keyWord.indexOf("&") != -1 ) {
            // 多个关键词以&分开作为参数传递过来,表示多个关键词为and的关系
                String[] split = keyWord.split("&");
                for (String item : split) {
                    BoolQueryBuilder postFilterKeyword = QueryBuilders.boolQuery();
                    if (!StringUtils.isBlank(item)) {
                        // 查询位置:locations:[articleTitle, articleContetn]
                        for (String fileName : locations) {
                            postFilterKeyword.should(QueryBuilders.matchPhraseQuery(fileName, item));
                        }
                    }
                    postFilter.must(postFilterKeyword);
                }
            } else {
                // 查询位置:locations:[articleTitle, articleContetn]
                BoolQueryBuilder postFilterKeyword = QueryBuilders.boolQuery();
                for (String fileName : locations) {
                    postFilterKeyword.should(QueryBuilders.matchPhraseQuery(fileName, keyWord));
                }
                postFilter.must(postFilterKeyword);
            }
        }
        if(timeType.equals(1)) {
            searchRequestBuilder.addSort(SortBuilders.fieldSort("sysCreateTime").unmappedType("date").order(SortOrder.DESC));
        }else{
            searchRequestBuilder.addSort(SortBuilders.fieldSort("sysModifyTime").unmappedType("date").order(SortOrder.DESC));
        }

        boolQueryBuilder.must(postFilter);
        searchRequestBuilder.setQuery(boolQueryBuilder);
        SearchResponse searchResponse = searchRequestBuilder.get();
        SearchHits hits = searchResponse.getHits();
        // 得到文章原id
        List<Long> ids = new ArrayList<>();
        for (SearchHit hit : hits) {
            String id = hit.getId();
            if (!StringUtils.isBlank(id)) {
                ids.add(Long.valueOf(id));
            }
        }

        Page resultPage = new Page();
        if (null == ids || 0 == ids.size()) {
            resultPage.setTotal(0L);
            resultPage.setRows(null);
        } else {
            List<ArticlePub> articlePubs = listPub(ids, timeType);
            resultPage.setTotal(hits.getTotalHits());
            resultPage.setRows(articlePubs);
        }
        return resultPage;

    }
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值