ElasticSearch实战之项目搜索高亮

本文介绍了如何在SpringBoot项目中使用ElasticSearch进行数据操作,包括创建索引、批量插入数据,以及实现高亮搜索功能,通过term查询并展示搜索结果中的高亮部分。
摘要由CSDN通过智能技术生成

在这里插入图片描述

1. 前情配置


为满足ElasticSearch可在项目中实现搜索高亮,我们需要先做一些前情配置

  1. 导入ElasticSearch依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
  1. 修改propertise配置
server.port=9090
spring.thymeleaf.cache=false
# 保证url可以输入中文,防止乱码
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true
  1. 构建一个搜索类对象,这里假设我们存在一个搜索对象为Content,其中我们要进行查询的字段是title
@AllArgsConstructor
@NoArgsConstructor
@Data
@Component
public class Content {
    private String title;
    private String img;
    private String price;
}

同时,假设我们拥有List<Content>数据集合,至此,我们做好了所有的前情准备


2、数据操作


2.1 操作API


我们拥有List<Content>数据集合,我们要将其插入到es

步骤分为三步:判断索引是否存在 -> 索引不存在则创建索引 -> 索引存在则插入文档

则数据操作的API分为三个,我们一一实现

API(1):判断索引是否存在

public boolean existIndex(String indexName) throws IOException {
    GetIndexRequest request = new GetIndexRequest(indexName);
    boolean isExists = client.indices().exists(request, RequestOptions.DEFAULT);
    return isExists;
}

API(2):创建索引

这里的indexName利用jd_goods传入,即我们创建的索引名称为jd_goods

public boolean createIndex(String indexName) throws IOException {
    CreateIndexRequest request = new CreateIndexRequest(indexName);
    CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
    return response.isAcknowledged();
}

API(3):批量插入数据

这里的indexName利用jd_goods传入,即我们将的List<Content>数据插入到jd_goods

public boolean bulkAddDoc(String indexName, List<Content> listContent) throws IOException {
    //判断是否存在索引
    if (indexService.existIndex()){
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("10s");
        //存入数据
        for (Content content : listContent) {
          bulkRequest.add(new IndexRequest(indexName)
          .source(JSON.toJSONString(content), XContentType.JSON));
        }
        //执行请求
        BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
        //不失败表示插入成功
        return !bulkResponse.hasFailures();
    }
    return false;
}

2.2 数据入库


整合上述方法,我们可以将List<Content>存入es

public boolean parseContent(String indexName,List<Content> list) throws IOException {
    //1. 某个获取数据的方法
    List<Content> list = function();
    //2. 判断索引是否存在,并且插入数据
    if (!indexService.existIndex(String indexName)){
        indexService.createIndex(String indexName);
    }
    //3. 插入数据
    return docService.bulkAddDoc(String indexName,list);
}

再次查看es,数据已经被插入

在这里插入图片描述

3. 高亮搜索


3.1 方法封装


封装用于搜索的方法,这里指定利用term搜索

//param搜索字段名称 searchWord搜索关键字,from和size用于分页
public List<Map<String, Object>> searchDoc(String indexName, String param, String searchWord, Integer from, Integer size) throws IOException {
    //构建搜索类
    SearchSourceBuilder searchBuilder = new SearchSourceBuilder();
    //匹配查询
    TermQueryBuilder termQuery = QueryBuilders.termQuery(param, searchWord);
    //设置超时
    searchBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

    //高亮
    HighlightBuilder highlightBuilder = new HighlightBuilder();
    //设置高亮的字段
    highlightBuilder.field(param);
    //多个高亮显示
    highlightBuilder.requireFieldMatch(false);
    highlightBuilder.preTags("<span style='color:red'>");
    highlightBuilder.postTags("</span>");
    searchBuilder.highlighter(highlightBuilder);

    //分页
    if (from <= 0){
        from = 0;
    }
    if (size != 0){
        searchBuilder.from(from);
        searchBuilder.size(size);
    }

    //封装搜索
    searchBuilder.query(termQuery);
    //创建查询请求,并将搜索类放入
    SearchRequest request = new SearchRequest(indexName).source(searchBuilder);
    //客户端查询请求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);

    //解析结果,第一次getHits()返回了全部的数据,包括版本信息等
    //第二次getHits()返回了数据中的查询对象
    //getSourceAsMap()表示将查询对象转化为map集合,其中键就是属性,值就是属性对应的值
    ArrayList<Map<String, Object>> list = new ArrayList<>();
    for(SearchHit hit:response.getHits().getHits()){
        //使用新的高亮字段,覆盖旧字段
        Map<String, Object> sourceAsMap = hit.getSourceAsMap();
        //获取全部的高亮字段
        Map<String, HighlightField> highlightFields = hit.getHighlightFields();
        HighlightField title = highlightFields.get(param);
        //开始替换,将旧的title值替换为高亮的值
        if (title != null){
            Text[] fragments = title.getFragments();
            StringBuilder newTitle = new StringBuilder();
            for (Text text:fragments){
                newTitle.append(text);
            }
            sourceAsMap.put(param,newTitle);
        }
        //再次添加进去
        list.add(sourceAsMap);
    }
    return list;
}

整合上述方法,假设我们在jd_goods中搜索title字段

public List<Map<String, Object>> searchContent(String indexName, String keyword,Integer from,Integer size) throws IOException {
    return docService.searchDoc("jd_goods","title",keyword,from,size);
}

3.2 高亮搜索


绑定浏览器地址,尝试查询

@GetMapping("/search/{keyword}/{from}/{size}")
public List<Map<String, Object>> searchContent(@PathVariable("keyword") String keyword,
@PathVariable("from") Integer from,@PathVariable("size") Integer size) throws IOException {
    return contentService.searchContent(keyword,from,size);
}

假设我们需要搜索jd_goods中搜索title字段包含java的字段,同时从第1条数据开始获取,获取的数据大小为20

访问浏览器,关键字已经被设置高亮,只需要传递到前端即可

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值