本网站的搜索栏集成ElasticSearch实现全文检索和权重排序(SpringBoot)
原来本网站的搜索栏只能对文章标题进行模糊搜索,作为一个博客网站,这样的搜索效率很低,显然对于读者的搜索体验来说就非常不友好 时隔半月,作者终于有时间和精力将搜索引擎ElasticSearch集成进本网站了。。。
集成
本文默认已安装es在服务器,安装教程请看另一篇文章:ElasticSearch安装以及配置教程
创建索引
PUT /blog_new
{
"mappings": {
"properties": {
"blogId": { "type": "long" },
"blogTitle": { "type": "text","analyzer": "text_anlyzer",
"search_analyzer": "ik_smart",
"copy_to": "all" },
"blogSubUrl": { "type": "ke、yword" },
"blogCoverImage": { "type": "text" },
"blogCategoryId": { "type": "integer" },
"blogCategoryName": { "type": "text" },
"blogTags": { "type": "text" },
"blogStatus": { "type": "byte" },
"blogViews": { "type": "long" },
"enableComment": { "type": "byte" },
"isDeleted": { "type": "byte" },
"createTime": { "type": "date", "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" },
"updateTime": { "type": "date", "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" },
"blogContent": { "type": "text","analyzer": "text_anlyzer",
"search_analyzer": "ik_smart",
"copy_to": "all" },
"all" : {
"type": "text",
"analyzer": "text_anlyzer",
"search_analyzer": "ik_smart"
}
}
},
"settings": {
"analysis": {
"analyzer": {
"text_anlyzer": {
"tokenizer": "ik_max_word"
}
}
}
}
}
引入pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
添加es配置
spring.elasticsearch.uris=xxx.xxx.xxx.xxx
spring.elasticsearch.connection-timeout= 1s
spring.elasticsearch.socket-timeout= 30s
创建实体类
@Data
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Document(indexName = "blog_new")
public class Blog {
@Id
private Long blogId;
@Field(type = FieldType.Text,analyzer = "ik_max_word")
private String blogTitle;
@Field(index = false,type = FieldType.Keyword)
private String blogSubUrl;
@Field(index = false,type = FieldType.Keyword)
private String blogCoverImage;
@Field(index = false,type = FieldType.Integer)
private Integer blogCategoryId;
@Field(index = false,type = FieldType.Keyword)
private String blogCategoryName;
@Field(index = false,type = FieldType.Keyword)
private String blogTags;
@Field(index = false,type = FieldType.Byte)
private Byte blogStatus;
@Field(index = false,type = FieldType.Long)
private Long blogViews;
@Field(index = false,type = FieldType.Byte)
private Byte enableComment;
@Field(index = false,type = FieldType.Byte)
private Byte isDeleted;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Field(index = false,type = FieldType.Date)
private Date createTime;
@Field(index = false,type = FieldType.Date)
private Date updateTime;
@Field(type = FieldType.Text,analyzer = "ik_max_word",store = true)
private String blogContent;
}
初始化数据
@Autowired
private ElasticsearchRestTemplate template; #注入template调用save()方法传入List批量导入数据
组装查询条件
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
.should(QueryBuilders.matchQuery("blogContent", keyword).boost(1))
.should(QueryBuilders.matchQuery("blogTitle", keyword).boost(10)); #标题权重设置为10
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(functionScoreQuery(boolQuery))
.withPageable(PageRequest.of(page, size/*, Sort.by(Sort.Order.desc("createTime"))*/)) #此处注解可时间排序
//.withHighlightFields(
// new HighlightBuilder.Field("blogContent").preTags("<em>").postTags("</em>"),
// new HighlightBuilder.Field("blogTitle").preTags("<em>").postTags("</em>")
//) #高亮显示,需要注意的是获得的Hits里面的数据是原数据,本就不会被修改,因此要继续拿highlight下的数据,即解析高亮结果,本文不做高亮处理
.build();
SearchHits<Blog> searchHits = template.search(searchQuery, Blog.class);
总结
做完这些就可以实现标题所说功能了,但这还不够,我们还没有做es与mysql的一致性处理,这个我会抽时间来写,之前的文章有过分析: