Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.3k views
in Technique[技术] by (71.8m points)

SpringBoot+ES+Ik查询的问题

目前来说主要是一个字段要精准匹配。一个字段要分词匹配。我现有的查询貌似只能分词匹配。精准匹配的效果没实现。不知道是怎么回事。

@Data
@Document(indexName = "interview", type = "blog", useServerConfiguration = true, createIndex = false)
public class ESCoderVo {

    @Id
    private Long id;

    @Field(type = FieldType.Keyword,analyzer = "ik_max_word")
    private String title;
    @Field(type = FieldType.Keyword,analyzer = "ik_smart")
    private  String  brief;
    @Field(type = FieldType.Keyword,analyzer = "ik_smart")
    private  String  label;
    @Field(type = FieldType.Keyword,analyzer = "ik_smart")
    private  String content;
    @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd HH:mm:ss")
    private String createTime;
    @Field(type = FieldType.Keyword,analyzer = "ik_smart")
    private String author;
    @Field(type = FieldType.Keyword,analyzer = "ik_smart")
    private  String  realUrl;
    @Field(type = FieldType.Keyword,analyzer = "ik_smart")
    private  String txt;
    @Field(type = FieldType.Keyword,analyzer = "ik_smart")
    private  String type;
    @Field(type = FieldType.Keyword,analyzer = "ik_smart")
    private  Integer phaseId;
}

使用的代码

   @ApiOperation(value = "面经搜索")
    @GetMapping(value = "/newcoder/search")
    public Page<ESCoderVo> search(@RequestParam(name = "pageNo",required = false) Integer pageNo,
                                  @RequestParam(name = "pageSize",required = false) Integer pageSize,
                                  @RequestParam(name = "keyword",required = false)String keyword
                                  ){
        if (pageNo == null){
            pageNo = 1;
        }
        if (pageSize==null){
            pageSize =10;
        }
        Pageable pageable = PageRequest.of(pageNo,pageSize);// (当前页, 每页记录数, 排序方式)
        //若索引不存在
//        coderRepository.deleteAll();
//        elasticsearchTemplate.deleteIndex(ESCoderVo.class);
        if(!elasticsearchTemplate.indexExists(ESCoderVo.class)){
            elasticsearchTemplate.deleteIndex(ESCoderVo.class);
            //创建索引
            elasticsearchTemplate.createIndex(ESCoderVo.class);
            List<NewCoderDTO> list = newCoderRepository.findAll();
            //将MySQL数据插入到ES
            if(!CollectionUtils.isEmpty(list)){
                List<ESCoderVo> esList = JSON.parseArray(JSON.toJSONString(list), ESCoderVo.class);
                coderRepository.saveAll(esList);
            }
        }
        BoolQueryBuilder builder = QueryBuilders.boolQuery();
//
        builder.must(QueryBuilders.termQuery("type","Java"));
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(builder)
                .withQuery(structureQuery("阿里百度"))
                .build();
        //builder.should(QueryBuilders.matchQuery("title","阿里百度").boost(6.0f).analyzer("ik_max_word"));
        //builder.should(QueryBuilders.matchQuery("label","阿里百度").boost(5.0f).analyzer("ik_smart"));
//        builder.should(QueryBuilders.matchQuery("txt","阿里百度").boost(4.0f).analyzer("ik_smart"));
        //Page<ESCoderVo> page = coderRepository.search(searchQuery);
        //System.out.println(page);
        Page<ESCoderVo> page = coderRepository.search(searchQuery);

        //Page<ESCoderVo> page = (Page<ESCoderVo>) coderRepository.search(builder,pageable);
        return page;

    }
    public DisMaxQueryBuilder structureQuery(String content) {
        //使用dis_max直接取多个query中,分数最高的那一个query的分数即可
        DisMaxQueryBuilder disMaxQueryBuilder = QueryBuilders.disMaxQuery();
        //boost 设置权重,只搜索匹配name和disrector字段
        //QueryBuilder typeQuery = QueryBuilders.termQuery("type","Java");
        QueryBuilder ikNameQuery = QueryBuilders.matchQuery("title", content).boost(2f);
        QueryBuilder ikBriefQuery = QueryBuilders.matchQuery("label", content).boost(2f);
        QueryBuilder ikDirectorQuery = QueryBuilders.matchQuery("txt", content).boost(2f);
        disMaxQueryBuilder.add(ikNameQuery);
        //disMaxQueryBuilder.add(typeQuery);
        disMaxQueryBuilder.add(ikBriefQuery);
        disMaxQueryBuilder.add(ikDirectorQuery);
        return disMaxQueryBuilder;
    }

目前查出来的包含了type为产品和C++类型等其他类型的数据

image


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

你说的对,如果type: text就无法用term精准搜索了,这时候只能用copy_to功能。
新建一个字段title_keyword切类型是type: keyword。,把title字段copy过去。精确搜索的时候用title_keyword字段。
参考文档链接:
https://www.elastic.co/guide/...
image.png


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...