spring boot+es 实现电商场景的搜索与高亮

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情

前言

在第5天的更文活动中,我们已经完成了使用kibana调用es的query进行常见的电商场景下的ik分词搜索。今天,我们将在spring boot项目中整合昨天实践的成果

定义高亮标识

我们想要实现搜索结果高亮,首先要把对应的结果加上固定的标识,使它能够在渲染的时候识别出来要高亮显示。我们先固定写死一个高亮显示的响应体,对应的接口定义如下

@RestController
@RequestMapping("es/search")
public class EsSearchController {
    @GetMapping("html")
    public void html(HttpServletResponse response) throws IOException {
        response.setHeader("Content-Type", "text/html; charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print(
                "<html><body>" +
                        "颜色是<span class='red'>红色</span>" +
                        "</body>" +
                        "<style> .red{color:red }</style>" +
                        "</html>");
        writer.flush();
        writer.close();
    }
}    
复制代码

我们启动项目(没有搭建项目的可以下载我的项目:gitee.com/liangminghu… 访问ip:port/es/search/html,即可显示如下的效果

1649254203(1).png

如何在es中设置高亮标识

想在es中设置响应高亮标识,我们需要使用highlight标签,我们以搜索“华为手机001为例”,按照sort默认升序,我们在kibana中的请求如下

post goods/_search
{
	"query": {
		"bool": {
			"should": [{
					"match": {
						"name": "华为手机001"
					}
				},
				{
					"match": {
						"keyWords": "华为手机001"
					}
				}
			]
		}
	},
	"highlight": {
		"pre_tags": ["<span class='red'>"],
		"post_tags": ["</span>"],
		"fields": {
			"name": {},
			"keyWords": {}
		}
	},
	"from": 0,
	"size": 2,
	"sort": {
		"sort": "asc"
	}
}
复制代码

关于query等标签我们已经在上一篇文章解释过了,这里主要介绍一下highlight里的标签

  • pre_tags+post_tags:这两个标签定义了分割出的结果以什么tag包围起来,和我们前端的<></>效果差不多
  • fields:定义要高亮搜索的属性,name代表名称要高亮,keyWords代表关键词要高亮\

注意:我们在创建索引的时候设置为ik搜索分词了,如果大家默认创建索引会走es的标注分词

使用spring boot整合我们的搜索

一开始我以为要整合es搜索到ik很难,知道我发现了8.1.2的client支持基于json封装请求体,瞬间感觉真香,以下的代码思路来自于官方文档:es官方文档,应该是最简单的集成es搜索的方法了


@GetMapping("doSearch")
public void doSearch(HttpServletResponse response, @RequestParam(value = "word") String word, @RequestParam(value = "sort", defaultValue = "sort") String sort) throws IOException {
    if (StringUtils.isBlank(word)) {
        return;
    }
    response.setHeader("Content-Type", "text/html; charset=utf-8");
    //初始化estClient
    RestClient restClient = RestClient.builder(
            new HttpHost("127.0.0.1", 9200, "http")).build();
    //设置请求方式和地址
    Request request = new Request(
            "POST",
            "goods/_search");
    //基于json构造查询
    request.setJsonEntity("{\"query\":{\"bool\":{\"should\":" +
        "[{\"match\":{\"name\":\"" + word + "\"}}," +
        "{\"match\":{\"keyWords\":\"" + word + "\"}}]}}," +
        "\"highlight\":{\"pre_tags\":[\"<span class='red'>\"]" +
        ",\"post_tags\":[\"</span>\"],\"fields\":{\"name\":{}," +
        "\"keyWords\":{}}},\"from\":0,\"size\":5,\"sort\":{\"sort\":\"asc\"}}");
    Response esRes = restClient.performRequest(request);
    log.info("{}", esRes);
    RequestLine requestLine = esRes.getRequestLine();
    HttpHost host = esRes.getHost();
    int statusCode = esRes.getStatusLine().getStatusCode();
    Header[] headers = esRes.getHeaders();
    String responseBody = EntityUtils.toString(esRes.getEntity());
##### log.info("{}{}{}{}{}", requestLine, host, statusCode, headers, responseBody);
    restClient.close();
    PrintWriter writer = response.getWriter();
    writer.print(
            "<html><body>" +
                    responseBody +
                    "</body>" +
                    "<style> .red{color:red }</style>" +
                    "</html>");
    writer.flush();
    writer.close();
}
复制代码

注意这里的client需要关闭,我们分别访问以下地址的得到的结果如下

  1. 搜索华为手机001:http://127.0.0.1:4001/es/search/doSearch?word=华为手机001

1649258062(1).png 可以看到name和keyWords都命中了 2. 搜搜麒麟:http://127.0.0.1:4001/es/search/doSearch?word=麒麟

1649258160(1).png 可以看到只命中了我们的关键词
综上我们已经完成了spring boot 集成 es8.1.2 ik分词高亮搜索。关于es的相关探索我们用了6天,希望大家在这6天中能有所收获

结语7

到今天,我们es相关的文章暂时告一段落了,从下期文章开始,我会从大数据方面或者taro多端开发实践中选择一个方向开始更文。欢迎大家多多点赞支持!\

猜你喜欢

转载自juejin.im/post/7083511302806568968