博客项目目录: 请戳这里
需求:用户登录后,点开搜索框,输入搜索内容,回车之后,就会跳转到对应的搜索页面
基本思路:
首先将所有的文章信息查询出来,同步到elasticsearch中,然后通过es进行搜索,得到对应的文档,之后转化成MyBatis的page信息,显示在前端页面
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-elasticsearchartifactId>
<version>2.1.1.RELEASEversion>
dependency>
<dependency>
<groupId>org.modelmappergroupId>
<artifactId>modelmapperartifactId>
<version>1.1.0version>
dependency>
一般来说,es的9200端口用于查询,9300端口用于连接程序
原来搜索框输入内容,回车之后,跳到固定的某一个网址进行搜索,现在修改之后,跳到我们写的接口进行搜索
<#include "/inc/layout.ftl" />
<@layout "搜索 - ${q}">
<#include "/inc/header-panel.ftl" />
<div class="layui-container">
<div class="layui-row layui-col-space15">
<div class="layui-col-md8">
<div class="fly-panel">
<div class="fly-panel-title fly-filter">
<a>您正在搜索关键字 “ ${q} ” - 共有 <strong>${pageData.total}strong> 条记录a>
<a href="#signin" class="layui-hide-sm layui-show-xs-block fly-right" id="LAY_goSignin" style="color: #FF5722;">去签到a>
div>
<ul class="fly-list">
<#list pageData.records as post>
<@plisting post>@plisting>
#list>
ul>
<@paging pageData>@paging>
div>
div>
<#include "/inc/right.ftl" />
div>
div>
@layout>
@RequestMapping("/search")
public String search(String q) {
req.setAttribute("q", q);
req.setAttribute("pageData", null);
return "search";
}
由于redis和es都包含netty相关的包,版本不匹配会存在包冲突,可在启动类加入相关语句解决。
测试:
有了索引之后,es就可以根据索引进行搜索,title是模糊匹配,其他的authorName、categoryName是完全匹配
@Data
@Document(indexName = "post", type = "post", createIndex = true)
public class PostDocment implements Serializable {
@Id
private Long id;
// ik分词器
@Field(type = FieldType.Text, searchAnalyzer = "ik_smart", analyzer = "ik_max_word")
private String title;
@Field(type = FieldType.Long)
private Long authorId;
@Field(type = FieldType.Keyword)
private String authorName;
private String authorAvatar;
private Long categoryId;
@Field(type = FieldType.Keyword)
private String categoryName;
private Integer level;
private Boolean recomment;
private Integer commentCount;
private Integer viewCount;
@Field(type = FieldType.Date)
private Date created;
}
PostRepository继承ElasticsearchRepository之后就可以进行jpa规范相关的操作,进行增删改查、控制page与Docment
@Repository
public interface PostRepository extends ElasticsearchRepository<PostDocment, Long> {
// 符合jpa命名规范的接口
}
事先安装好kibana,绑定es,并启动kibana。
然后启动项目,发现es多出了我们刚才创建的post索引,以及相关的属性
public interface SearchService {
IPage search(Page page, String keyword);
}
3.实现类
@Override
public IPage search(Page page, String keyword) {
// 分页信息 mybatis plus的page 转成 jpa的page
Long current = page.getCurrent() - 1;
Long size = page.getSize();
Pageable pageable = PageRequest.of(current.intValue(), size.intValue());
// 搜索es得到pageData
MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keyword,
"title", "authorName", "categoryName");
org.springframework.data.domain.Page<PostDocment> docments = postRepository.search(multiMatchQueryBuilder, pageable);
// 结果信息 jpa的pageData转成mybatis plus的pageData
IPage pageData = new Page(page.getCurrent(), page.getSize(), docments.getTotalElements());
pageData.setRecords(docments.getContent());
return pageData;
}
要在es搜索,首先es要有数据,所以我们在页面设计一个按钮,按下按钮,便会将mybatis查到的所有文章信息同步到es。
1.请求层
预计最多存储1千万条记录,用一个循环进行同步,没查完一页就同步一次,当一页没有1万条记录时,说明是最后一页,终止查询。
@ResponseBody
@PostMapping("/initEsData")
public Result initEsData() {
int size = 10000;
Page page = new Page();
page.setSize(size);
long total = 0;
for (int i = 1; i < 1000; i ++) {
page.setCurrent(i);
IPage<PostVo> paging = postService.paging(page, null, null, null, null, null);
int num = searchService.initEsData(paging.getRecords());
total += num;
// 当一页查不出10000条的时候,说明是最后一页了
if(paging.getRecords().size() < size) {
break;
}
}
return Result.success("ES索引初始化成功,共 " + total + " 条记录!", null);
}
2.接口
3.实现类
利用modelMapper将查到的vo记录,映射成Docment,存到es。
@Override
public int initEsData(List<PostVo> records) {
if(records == null || records.isEmpty()) {
return 0;
}
List<PostDocment> documents = new ArrayList<>();
for(PostVo vo : records) {
// 映射转换
PostDocment postDocment = modelMapper.map(vo, PostDocment.class);
documents.add(postDocment);
}
postRepository.saveAll(documents);
return documents.size();
}
4.配置modelMapper
5.修改set.ftl
在管理员的set界面下新增“同步ES”栏,以及“同步ES数据”按钮
6.测试:
管理员设置页面多出“同步ES”栏目
点击“同步ES数据”按钮:
查看kibana,出现对应文档:
https://github.com/MarkerHub/eblog