第十一节 SpringBoot使用ES进行高亮查询

亮子 2022-02-14 01:14:17 22163 0 0 0

1、添加依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>

2、修改版本

    <properties>
        <java.version>1.8</java.version>
        <elasticsearch.version>7.8.1</elasticsearch.version>
    </properties>

3、创建实体类

package com.shenmazong.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

/**
 * 小说表
 * @TableName tb_story
 */
@TableName(value ="tb_story")
@Data
@Document(indexName = "tb_story", shards = 1, replicas = 1)
public class TbStory implements Serializable {
    /**
     * 小说ID
     */
    @TableId(type = IdType.AUTO)
    @Id
    private Integer id;

    /**
     * 小说名字
     */
    @Field(type = FieldType.Text, analyzer = "ik_smart")
    private String name;

    /**
     * 小说作者
     */
    @Field(type = FieldType.Keyword)
    private String author;

    /**
     * 小说内容
     */
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String content;

    /**
     * 点赞状态:0支持1反对
     */

    @Field(type = FieldType.Integer)
    private Integer status;

    /**
     * 软删除:0正常1删除
     */
    @Field(type = FieldType.Integer)
    private Integer deleted;

    /**
     * 创建时间
     */
    @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
    private Date createTime;

    /**
     * 修改时间
     */
    @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
    private Date updateTime;

    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
}

4、分页、高亮、多条件查询

package com.shenmazong;

import com.shenmazong.pojo.TbStory;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.List;

/**
 * @author 军哥
 * @version 1.0
 * @description: 分页、高亮、多条件的ES查询
 * @date 2022/2/12 10:34
 */

@SpringBootTest
public class ElasticSearchTest {

    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Test
    public void testEsPage() {
        // 分页
        Pageable pageable = PageRequest.of(0, 10);

        // 查询条件
//        QueryBuilders.boolQuery();
//        QueryBuilders.termQuery();
//        QueryBuilders.termsQuery();
//        QueryBuilders.matchQuery();
//        QueryBuilders.multiMatchQuery();
//        QueryBuilders.rangeQuery();
        TermQueryBuilder termQueryBuilder1 = QueryBuilders.termQuery("content", "会议");
        TermQueryBuilder termQueryBuilder2 = QueryBuilders.termQuery("name", "精神");

        BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();
        // where content like '%会议%' and name like '%%精神'
//        boolQueryBuilder.must(termQueryBuilder1).must(termQueryBuilder2);
        boolQueryBuilder.must(termQueryBuilder1).mustNot(termQueryBuilder2);

        // 结果排序
        SortBuilder order = new FieldSortBuilder("createTime").order(SortOrder.DESC);

        // 设置高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<font color='red'>").postTags("</font>").field("content");

        // 查询builder:实际上组合的一个json字符串
        // select * from tb_story where content like '%会议%' order by createTime desc limit 0,10
        // select _id from tb_story where content like '%会议%' order by createTime desc limit 0,10
        NativeSearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withPageable(pageable)
                .withSort(order)
                .withHighlightBuilder(highlightBuilder)
//                .withHighlightFields(new HighlightBuilder.Field("name").preTags(preTag).postTags(postTag))
//                .withHighlightFields(new HighlightBuilder.Field("tags").preTags(preTag).postTags(postTag))
                .build();

        // 进行查询
        SearchHits<TbStory> search = elasticsearchRestTemplate.search(query, TbStory.class);
        long totalHits = search.getTotalHits();
        System.out.println("totalHits="+totalHits);

        List<SearchHit<TbStory>> searchHits = search.getSearchHits();
        searchHits.forEach(row -> {
            // 普通结果
            TbStory tbStory = row.getContent();
            System.out.println(tbStory);

            // 高亮结果
            List<String> content = row.getHighlightField("content");
            if(content != null && content.size()>0) {
                // 取出结果并替换原文
                String s = content.get(0);
                tbStory.setContent(s);
            }

            // 取第二个高亮

            System.out.println("hi:"+tbStory);

        });
    }
}

5、多个高亮字段

        NativeSearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withPageable(pageable)
                .withSort(order)
                .withHighlightBuilder(highlightBuilder)
                .withHighlightFields(new HighlightBuilder.Field("name").preTags(preTag).postTags(postTag))
                .withHighlightFields(new HighlightBuilder.Field("tags").preTags(preTag).postTags(postTag))
                .build();