开始前准备
springdata elastic接入方法
https://blog.csdn.net/qq_36289377/article/details/105843733
对应版本
elasticsearch 6.8
spring-boot 2.2.2.RELEASE
spring-boot-starter-data-elasticsearch 2.2.2.RELEASE
本文创作时,es最新版为7.2,可以兼容,6.0以下版本需要根据版本改部分代码,主要是低版本的几个Hits类不同,其他差别不大,可以自己查,这里不提供具体哪几个类。未来更高版本也不确定能否可用,自己去判断。
原理分析
实现关键词高亮在本质上是利用es的自定义ResultMapper功能,将匹配到的结果通过反射替换为加入高亮标识的片段的过程,对于这一点来说,网上相关文档数不胜数,并不是说完全不能用,但是对于聚合字段的处理基本是选择性忽略,而且对于使用的es client也停留在较老的版本,如果毫不思考直接使用,通常会遇到很多问题,别问我怎么知道的😓。
第一步:ES数据结构设计
如果你的es映射类含聚合信息:如数组字段、对象字段、对象数组字段,如
/**
* es公司信息聚合映射实体类
* @author tino
* @date 2020/7/27
*/
@org.springframework.data.elasticsearch.annotations.Document(indexName = "tino", type = "company_info", shards = 1, replicas = 0)
public class EsCompanyInfoModel extends BaseModel {
/**
* 公司名称
*/
private String companyName;
/**
* 数组
*/
private List<BizProductModel> products;
/**
* 公司分类
*/
private List<String> categories;
/**
* 公司案例
*/
private CompanyCaseModel companyCaseModel;
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public List<BizProductModel> getProducts() {
return products;
}
public void setProducts(List<BizProductModel> products) {
this.products = products;
}
public List<String> getCategories() {
return categories;
}
public void setCategories(List<String> categories) {
this.categories = categories;
}
public CompanyCaseModel getCompanyCaseModel() {
return companyCaseModel;
}
public void setCompanyCaseModel(CompanyCaseModel companyCaseModel) {
this.companyCaseModel = companyCaseModel;
}
}
那么你可能需要将聚合的对象数组、对象更改数据结构为:仅包含基本类型数组、字符串类型数组。
原因时对象数组的在反射时,想通过反射替换对象数组中对应索引的对象的字段操作起来比较困难,所以我们需要尽量简化数据结构,只将需要匹配的字段单独拿出来放到字符串数组中(应该没有业务会全字段匹配吧,如果有建议从设计层面去杜绝),更改数据结构后,需要清理ES中的旧数据
## 删除所有
index/type/_delete_by_query
{
"query": {
"match_all": {
}
}
}
调整后的数据结构
/**
* es公司信息聚合映射实体类
* @author tino
* @date 2020/7/27
*/
@org.springframework.data.elasticsearch.annotations.Document(indexName = "tino", type = "company_info", shards = 1, replicas = 0)
public class EsCompanyInfoModel extends BaseModel {
/**
* 产品名称
*/
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
private List<String> productNames;
/**
* 产品线路
*/
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
private List<String> productRoutes;
/**
* 产品分类
*/
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
private List<String> productCategories;
/**
* 标签
*/
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
private List<String> productLabels;
/**
*
*/
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
private List<String> productIntros;
/**
* 公司案例标题
*/
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
private List<String> caseTiles;
/**
* 公司案例内容
*/
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
private List<String> casesValueContents;
public List<String> getProductNames() {
return productNames;
}
public void setProductNames(List<String> productNames) {
this.productNames = productNames;
}
public List<String> getProductRoutes() {
return productRoutes;
}
public void setProductRoutes(List<String> productRoutes) {
this.productRoutes = productRoutes;
}
public List<String> getProductCategories() {
return productCategories;
}
public void setProductCategories(List<String> productCategories) {
this.productCategories = productCategories;
}
public List<String> getProductLabels() {
return productLabels;
}
public void setProductLabels(List<String> productLabels) {
this.productLabels = productLabels;
}
public List<String> getProductIntros() {
return productIntros;
}
public void setProductIntros(List<String> productIntros) {
this.productIntros = productIntros;
}
publi