Elasticsearch
版本7.8.0
项目源码
链接:https://pan.baidu.com/s/1TY1KzuVa9sA_8n57BkdA-Q
提取码:j0kh
1、Elasticsearch安装
1、下载Elasticsearch,解压
bin:启动文件
config:配置文件
log4j2.properties:日志配置文件
jvm.options:java虚拟机的配置
elasticsearch.yml:es的配置文件 默认9200端口 跨域
data:索引数据目录
lib:相关类库Jar包
logs:日志目录
modules:功能模块
plugins:插件
2、双击ElasticSearch下的bin目录中的elasticsearch.bat启动,控制台显示的日志(等待启动完
毕!):
3、然后在浏览器访问:http://localhost:9200 得到如下信息,说明安装成功了:
注意:需要NodeJS的环境,我们讲解大前端进阶已经安装过了,没安装的需要安装!
Head是elasticsearch的集群管理工具,可以用于数据的浏览查询!被托管在github上面!
地址: https://github.com/mobz/elasticsearch-head/
1、下载 elasticsearch-head-master.zip
2、解压之后安装依赖!
npm install
npm run start
3、连接测试http://localhost:9100/发现,存在跨域问题:配置es,elasticsearch.yml
# 跨域配置:
http.cors.enabled: true
http.cors.allow-origin: "*"
4、启动ElasticSearch,使用head工具进行连接测试!http://localhost:9100/
2、Kibana安装
Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索、查看交互存储在Elasticsearch索
引中的数据。使用Kibana,可以通过各种图表进行高级数据分析及展示。Kibana让海量数据更容易理
解。它操作简单,基于浏览器的用户界面可以快速创建仪表板(dashboard)实时显示Elasticsearch查
询动态。设置Kibana非常简单。无需编码或者额外的基础架构,几分钟内就可以完成Kibana安装并启动
Elasticsearch索引监测。
官网:https://www.elastic.co/cn/kibana
1、下载Kibana https://www.elastic.co/cn/downloads/kibana (注意版本对应关系)
2、将压缩包解压即可(需要一些时间)!
3、安装依赖【好像不需要】
npm install
3、然后进入到bin目录下,启动服务就可以了(需要等待启动完成),ELK基本上都是拆箱即用的
4、汉化Kibana:修改Kibana为中文config目录下的kibana.yml文件,添加
i18n.locale: "zh-CN"
3、ES核心概念
1、索引
2、字段类型(mapping)
3、文档(documents)
elasticsearch是面向文档,关系行数据库 和 elasticsearch 客观的对比!
物理设计:
elasticsearch 在后台把每个索引划分成多个分片,每分分片可以在集群中的不同服务器间迁移
倒排索引:
elasticsearch使用的是一种称为倒排索引的结构,采用Lucene倒排索作为底层。这种结构适用于快速的
全文搜索, 一个索引由文档中所有不重复的列表构成,对于每一个词,都有一个包含它的文档列表。
4、IK分词器
1、下载ik分词器的包,Github地址:https://github.com/medcl/elasticsearch-analysis-ik/ (版本要对
应)
2、下载后解压,并将目录拷贝到ElasticSearch根目录下的 plugins 目录中。
3、重新启动 ElasticSearch 服务,在启动过程中,你可以看到正在加载"analysis-ik"插件的提示信息,
服务启动后,在命令行运行 elasticsearch-plugin list
命令,确认 ik 插件安装成功。
4、使用kibana测试
1、查看不同的分词器效果
ik_smart最少切分
ik_max_word最细粒度划分
ik_smart最少切分
ik_max_word最细粒度划分,穷尽词库
2、问题:我们自己的词未被识别,被拆分了
我们测试发现“岩弟弟”被拆分了,我们不想“岩弟弟”被拆分,岩弟弟是一个词,那我们需要配置分词器
配置分词器识别自己需要的词为一个词,而不拆分,修改D:\es\elasticsearch-7.8.0\plugins\elasticsearch-analysis-ik-7.8.0\config\IKAnalyzer.cfg.xml
,
在config目录下新建lxw.dic
,输入岩弟弟
在IKAnalyzer.cfg.xml
中添加lxw.dic
重启ES,重新测试“岩弟弟”,发现岩弟弟
变成了一个完整的词
5、Rest风格
5.1、Rest风格
1、在控制台输入以下命令:
// 命令解释
// PUT 创建命令 test1 索引 type1 类型 1 id
PUT /test1/type1/1
{
"name":"岩弟弟", // 属性
"age":3 // 属性
}
返回结果 (是以REST ful 风格返回的 ):
#! Deprecation: [types removal] Specifying types in document index requests is deprecated, use the typeless endpoints instead (/{index}/_doc/{id}, /{index}/_doc, or /{index}/_create/{id}).
// 警告信息:不支持在文档索引请求中指定类型
// 而是使用无类型的端点(/{index}/_doc/{id}, /{index}/_doc,或/{index}/_create/{id})。
{
"_index" : "test1", //索引
"_type" : "type1", //类型
"_id" : "1", //id
"_version" : 1, //版本
"result" : "created", //操作类型
"_shards" : { //分片信息
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
2、查看
3、那么 name 这个字段用不用指定类型呢。毕竟我们关系型数据库 是需要指定类型的啊 !
- 字符串类型
text 、 keyword - 数值类型
long, integer, short, byte, double, float, half_float, scaled_float - 日期类型
date - te布尔值类型
boolean - 二进制类型
binary - 等等......
4、指定字段类型
PUT /test2
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"age": {
"type": "long"
},
"birthday":{
"type": "date"
}
}
}
}
查看GET命令
5、查看默认的信息
控制台输入
head查看
GET查看,发现自动匹配类型
拓展:通过GET _cat/indices?v
等命令可以获取默认信息
5.2、索引【增删改查Rest风格简单使用】
PUT增
PUT /test3/_doc/1
{
"name": "岩弟弟",
"age": 15,
"borthday": "2000-03-03"
}
PUT改(有数据的情况下,版本号+1)
PUT /test3/_doc/1
{
"name": "岩鸽鸽",
"age": 15,
"borthday": "2000-03-03"
}
POST进行修改
POST /test3/_doc/1/_update
{
"doc":{
"name": "张三"
}
}
删除索引
DELETE test1
GET查
GET test3/_doc/1
6、文档的操作【增删改查】【重点】
6.1、增
PUT /lxw/user/1
{
"name": "岩弟弟",
"age": 23,
"desc": "牛牛牛",
"tags": ["k1","k2","k3"]
}
6.2、删
DELETE /lxw/user/4
6.3、改
PUT 【如果不传递值,会被置空】
PUT /lxw/user/1
{
"name": "岩弟弟",
"age": 23,
"desc": "牛牛牛222",
"tags": ["k1","k2","k3"]
}
改POST【提倡用这个】_update
POST /lxw/user/1/_update
{
"doc":{
"name": "岩弟弟POST"
}
}
6.4、查【重点】
操作:
- 匹配
- 按照条件查询
- 精确查询
- 区间范围查询
- 匹配字段过滤
- 多条件查询
- 高亮查询
1、简单的搜索
GET lxw/user/1
2、简单的条件查询询_search?q=
GET lxw/user/_search?q=name:岩弟弟
3、复杂查询
GET lxw/user/_search
{
"query":{
"match": {
"name": "岩"
}
}
}
结果
4、限制显示字段
输出结果不需要那么多
GET lxw/user/_search
{
"query":{
"match": {
"name": "岩"
}
},
"_source":["name","desc"]
}
结果
5、排序asc和desc
GET lxw/user/_search
{
"query":{
"match": {
"name": "岩"
}
},
"sort":{
"age":{
"order": "desc"
}
}
}
结果
6、分页查询
from
从第几个数据开始
size
返回多少条数据
GET lxw/user/_search
{
"query":{
"match": {
"name": "岩"
}
},
"sort":{
"age":{
"order": "desc"
}
},
"from":0,
"size":1
}
结果:
7、布尔值查询
多条件查询bool +must +should +must_not+filter
-
must( and ) 所有条件都要符合 where id =1 and name = xxx
-
should( or ) 所有条件都要符合 where id =1 or name = xxx
使用must,等价and
GET lxw/user/_search
{
"query":{
"bool": {
"must": [
{
"match": {
"name": "岩"
}
},
{
"match": {
"age": 28
}
}
]
}
}
}
结果:
使用should,等价or
GET lxw/user/_search
{
"query":{
"bool": {
"should": [
{
"match": {
"name": "岩"
}
},
{
"match": {
"age": 28
}
}
]
}
}
}
结果:查询出两个数据
使用must_not(not)
GET lxw/user/_search
{
"query":{
"bool": {
"must_not": [
{
"match": {
"name": "岩"
}
}
]
}
}
}
结果
使用filter进行数据过滤
GET lxw/user/_search
{
"query":{
"bool": {
"must": [
{
"match": {
"name": "岩"
}
}
],
"filter": [
{
"range": {
"age": {
"gte": 10,
"lte": 25
}
}
}
]
}
}
}
gt,gte,lt,lte缩写的含义
-
gt: greater than 大于
-
gte: greater than or equal 大于等于
-
lt: less than 小于
-
lte: less than or equal 小于等于
结果:
8、关于分词:
-
模糊查询match,会使用分词器解析(先分析文档,然后通过分析的文档进行查询)
-
精确查询term,直接通过倒排索引精确查询【效率高】
使用match
GET lxw/user/_search
{
"query":{
"match": {
"tags": "男 老"
}
}
}
结果:
term精确查询多个值
GET testdb/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"t1": "22"
}
},
{
"term": {
"t1": "33"
}
}
]
}
}
}
9、两个类型 text keyword
-
text会被分词器解析
-
keyword不会被分词器解析
创建表,插入三条数据
PUT testdb
{
"mappings": {
"properties": {
"name":{
"type": "text"
},
"desc":{
"type": "keyword"
}
}
}
}
PUT testdb/_doc/1
{
"name": "岩弟弟name",
"desc": "岩弟弟desc"
}
PUT testdb/_doc/2
{
"name": "岩弟弟name",
"desc": "岩弟弟desc2"
}
PUT testdb/_doc/3
{
"name": "岩弟弟name",
"desc": "岩弟弟desc3"
}
GET【keyword】,整体,没有被分词,没有被分析
GET _analyze
{
"analyzer": "keyword",
"text": "岩弟弟name"
}
GET【standard】,被拆分
GET _analyze
{
"analyzer": "standard",
"text": "岩弟弟name"
}
GET 对text字段
GET testdb/_search
{
"query":{
"term":{
"name": "岩"
}
}
}
GET 对keyword字段
GET testdb/_search
{
"query":{
"term":{
"desc": "岩弟弟desc"
}
}
}
10、高亮查询
高亮显示
GET lxw/user/_search
{
"query":{
"match": {
"name": "岩弟弟"
}
},
"highlight": {
"fields": {
"name": {}
}
}
}
自动生成高亮前缀
自定义高亮
GET lxw/user/_search
{
"query":{
"match": {
"name": "岩弟弟"
}
},
"highlight": {
"pre_tags": "<p class='key' style='color:red'> ",
"post_tags": "</p>",
"fields": {
"name": {}
}
}
}
效果
7、集成SpringBoot
官方文档Elasticsearch Clients
https://www.elastic.co/guide/en/elasticsearch/client/index.html
1、找到原生的依赖
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.8.1</version>
</dependency>
2、找对象
3、分析这个类中的方法
配置基本的项目
在properties里面更改版本依赖,与本地版本一致
<!--自定义es版本依赖,保证和本地版本一致-->
<elasticsearch.version>7.8.1</elasticsearch.version>
新建配置类
package com.badwei.esapi.config;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// spring 两步骤
// 1.找对象
// 2.放到spring中待用
// 3.springboot,分析源码
@Configuration //xml
public class ESClientConfig {
// spring
@Bean
public RestHighLevelClient restHighLevelClient(){
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http")));
return client;
}
}
7.1、关于索引的API操作
@Autowired
@Qualifier("restHighLevelClient")
private RestHighLevelClient client;
// 测试索引的创建
@Test
void testCreateIndex() throws IOException {
//1.创建索引请求
CreateIndexRequest request = new CreateIndexRequest("lxw_index");
//2.执行
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
System.out.println(createIndexResponse);
}
//测试获取索引
@Test
void testExistIndex() throws IOException {
GetIndexRequest request = new GetIndexRequest("lxw_index");
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
}
//测试删除索引
@Test
void testDeleteIndex() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("lxw_index");
AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
System.out.println(delete.isAcknowledged());
}
7.2、关于文档的API操作
引入fastjson
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.78</version>
</dependency>
//测试添加文档
@Test
void testAddDocument() throws IOException {
User user = new User("岩弟弟", 3);
//创建请求
IndexRequest request = new IndexRequest("lxw_index");
//规则 put /lxw_index/_doc/1
request.id("1");
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
//将我们的数据放入请求 json
request.source(JSON.toJSONString(user), XContentType.JSON);
//客户端发送请求
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
System.out.println(indexResponse.toString());
System.out.println(indexResponse.status());
}
//测试获取文档,判断是否存在get /index/doc/1
@Test
void testIsExists() throws IOException {
GetRequest getRequest = new GetRequest("lxw_index", "1");
//不获取返回的 _source 的上下文
getRequest.fetchSourceContext(new FetchSourceContext(false));
getRequest.storedFields("_none_");
boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);
System.out.println(exists);
}
//获取文档的信息
@Test
void testGetDocument() throws IOException{
GetRequest getRequest = new GetRequest("lxw_index", "1");
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
System.out.println(getResponse.getSourceAsString());
System.out.println(getResponse);
}
//更新文档的信息
@Test
void testUpdateDocument() throws IOException {
UpdateRequest updateRequest = new UpdateRequest("lxw_index", "1");
updateRequest.timeout("1s");
User user = new User("岩弟弟2号", 110);
updateRequest.doc(JSON.toJSONString(user),XContentType.JSON);
UpdateResponse update = client.update(updateRequest, RequestOptions.DEFAULT);
System.out.println(update.status());
}
//删除文档记录
@Test
void testDeleteDocument() throws IOException {
DeleteRequest deleteRequest = new DeleteRequest("lxw_index","1");
deleteRequest.timeout("3s");
DeleteResponse delete = client.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println(delete.status());
}
//特殊的:真的项目一般会批量插入数据
@Test
void testBulkDocument() throws IOException{
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("10s");
ArrayList<User> userList = new ArrayList<>();
userList.add(new User("lxw1",31));
userList.add(new User("lxw2",32));
userList.add(new User("lxw3",33));
userList.add(new User("lxw4",34));
userList.add(new User("lxw5",35));
userList.add(new User("lxw6",36));
for (int i = 0; i < userList.size(); i++) {
//批量更新,删除,修改这里就行了
bulkRequest.add(new IndexRequest("lxw_index")
.id(""+(i+1)) //这里不设置id的话,会随机id
.source(JSON.toJSONString(userList.get(i)),XContentType.JSON));
}
BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
System.out.println(bulkResponse.hasFailures());
}
/*
SearchRequest 搜索请求
SearchSourceBuilder 条件构造
HighlightBuilder 构建高亮
TermQueryBuilder 精确查询
MathAllQueryBuilder
xxx QueryBuilder 对应我们刚才看到的所有命令
*/
//查询
@Test
void testSearchDocument() throws IOException{
SearchRequest searchRequest = new SearchRequest(ESconst.ES_INDEX);
//public static final String ES_INDEX = "lxw_index";
//构建搜索的条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "lxw1");//精确
// MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();//匹配所有
SearchSourceBuilder query = searchSourceBuilder.query(termQueryBuilder);
//分页
// searchSourceBuilder.from();
// searchSourceBuilder.size();
searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(searchResponse.getHits()));
System.out.println("=========================");
for (SearchHit documentFields : searchResponse.getHits().getHits()) {
System.out.println(documentFields.getSourceAsMap());
}
}
8、京东搜索实战
8.1、环境
新建springboot项目,导入默认,web,ES,Thymeleaf依赖
修改ES版本依赖,导入fastjson依赖
<!-- 自定义es版本依赖,保证和本地版本一致-->
<elasticsearch.version>7.8.0</elasticsearch.version>
导入静态资源,
新建IndexController,用来访问index.html
启动springboot项目。
8.2、爬虫
导入jsoup依赖
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.2</version>
</dependency>
爬虫
//获得请求
//前提,需要联网
String url = "https://search.jd.com/Search?keyword=java";
//解析网页
Document document = Jsoup.parse(new URL(url),30000);
//所有在js中使用的方法在这都可以用
Element element = document.getElementById("J_goodsList");
// System.out.println(element.html());
//获取所有的li元素
Elements elementsByTag = element.getElementsByTag("li");
for (Element element1 : elementsByTag) {
String img = element1.getElementsByTag("img").eq(0).attr("data-lazy-img");
String price = element1.getElementsByClass("p-price").eq(0).text();
String title = element1.getElementsByClass("p-name").eq(0).text();
System.out.println("=========================");
System.out.println(img);
System.out.println(price);
System.out.println(title);
}
8.3、导入到ES
编写过程中的html修改未体现在文档中
编写Pojo
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Content {
private String title;
private String img;
private String price;
}
把爬虫封装成一个方法
@Component
public class HtmlParseUtil {
// public static void main(String[] args) throws IOException {
//
// new HtmlParseUtil().parseJD("java").forEach(System.out::println);
//
// }
public List<Content> parseJD(String keyword) throws IOException {
String url = "https://search.jd.com/Search?keyword="+keyword;
Document document = Jsoup.parse(new URL(url),30000);
Element element = document.getElementById("J_goodsList");
Elements elementsByTag = element.getElementsByTag("li");
ArrayList<Content> contentList = new ArrayList<>();
for (Element element1 : elementsByTag) {
String img = element1.getElementsByTag("img").eq(0).attr("data-lazy-img");
String price = element1.getElementsByClass("p-price").eq(0).text();
String title = element1.getElementsByClass("p-name").eq(0).text();
Content content = new Content(title, img, price);
contentList.add(content);
}
return contentList;
}
}
编写ESConfig
package com.badwei.esjd.config;
// spring 两步骤
// 1.找对象
// 2.放到spring中待用
// 3.springboot,分析源码
@Configuration //xml
public class ESClientConfig {
// spring
@Bean
public RestHighLevelClient restHighLevelClient(){
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http")));
return client;
}
}
编写Service,调用爬虫方法, 将爬取的数据导入ES中
//业务编写
@Service
public class ContentService {
@Autowired
private RestHighLevelClient restHighLevelClient;
//解析数据放入es索引中
public Boolean parseContext(String keyword) throws IOException {
List<Content> contents = new HtmlParseUtil().parseJD(keyword);
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("2m");
for (int i = 0; i < contents.size(); i++) {
bulkRequest.add(new IndexRequest("jd_goods")
.source(JSON.toJSONString(contents.get(i)),XContentType.JSON));
}
BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
return !bulk.hasFailures();
}
}
编写Controller调用这个service方法
@RestController
public class ContentController {
@Autowired
private ContentService contentService;
@GetMapping("/parse/{keyword}")
public Boolean parse(@PathVariable("keyword") String keyword) throws IOException {
return contentService.parseContext(keyword);
}
}
这样就把爬取出来的数据导入到ES中了
8.4、ES数据获取
然后编写service数据获取
//获取数据
public List<Map<String,Object>> searchPage(String keyword,int pageNo,int pageSize) throws IOException {
if (pageNo<=1){
pageNo=1;
}
//条件搜索
SearchRequest searchRequest = new SearchRequest("jd_goods");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//分页
searchSourceBuilder.from(pageNo);
searchSourceBuilder.size(pageSize);
//精准匹配
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", keyword);
searchSourceBuilder.query(termQueryBuilder);
searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//执行搜索
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
ArrayList<Map<String,Object>> list = new ArrayList<>();
//结果解析
for (SearchHit documentFields : searchResponse.getHits().getHits()) {
list.add(documentFields.getSourceAsMap());
}
return list;
}
然后controller调用
@GetMapping("/search/{keyword}/{pageNo}/{pageSize}")
public List<Map<String,Object>> search(@PathVariable("keyword") String keyword,
@PathVariable("pageNo") int pageNo,
@PathVariable("pageSize") int pageSize) throws IOException {
return contentService.searchHighlightPage(keyword, pageNo, pageSize);
}
然后访问测试
8.5、关键字高亮
编写service
//实现搜索高亮
public List<Map<String,Object>> searchHighlightPage(String keyword,int pageNo,int pageSize) throws IOException {
if (pageNo<=1){
pageNo=1;
}
//条件搜索
SearchRequest searchRequest = new SearchRequest("jd_goods");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//分页
searchSourceBuilder.from(pageNo);
searchSourceBuilder.size(pageSize);
//精准匹配
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", keyword);
searchSourceBuilder.query(termQueryBuilder);
searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("title");
highlightBuilder.requireFieldMatch(false);//多个高亮关闭
highlightBuilder.preTags("<span style='color:red'>");
highlightBuilder.postTags("</span>");
searchSourceBuilder.highlighter(highlightBuilder);
//执行搜索
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
ArrayList<Map<String,Object>> list = new ArrayList<>();
//结果解析
for (SearchHit documentFields : searchResponse.getHits().getHits()) {
//解析高亮的字段
Map<String, HighlightField> highlightFields = documentFields.getHighlightFields();
HighlightField title = highlightFields.get("title");
Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();
if (title!=null){
Text[] fragments = title.fragments();
String n_title = "";
for (Text fragment : fragments) {
n_title+=fragment;
}
sourceAsMap.put("title",n_title);//高亮的字段替换原来的内容
}
list.add(sourceAsMap);
}
return list;
}
测试实现高亮展示
完成
评论区