上一篇博文,我们整合了一下ES6,实现了添加和查找数据的操作,但是只是简单的根据ID操作而已,我研究ES的目标是可以用在博客平台上作为一个高效率的搜索框架,根据用户输入内容,高效的查询出博主名称、标签名称、博文标题、博文正文中包含有用户输入关键字的博主、标签、博文来。用普通的数据库like当然不行啦,难以想象效率有多低。所以这里就用ES,当然为了提高效率,肯定得多耗费储存,空间换时间嘛,守恒定律就算在代码领域也是符合的。
1、本实例目标
根据用户输入的内容,分页查询出标题,正文中包含这些内容的博文,返回给页面。这里的包含不是全包含,只需要含有用户输入的内容也得检索出来。
我这篇博文完全是基于SpringBoot2.0整合 Elasticsearch6实战这一篇搭建来的。
2、实体结构Topic
//elasticsearch 6.0.0及之后移除了一个索引允许映射多个类型的操作(Removal of mapping types)
@Document(indexName="topic",type="topic")
public class Topic {
@Id
private Long id;
private String title;
private String content;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
因为elasticsearch 6.0.0及之后移除了一个索引允许映射多个类型的操作(Removal of mapping types),所以这里索引名称和类型都用topic。话说我的博客系统数据库设计是Topic表和Content表分开来的,这里只用一个实体不会冲突么?其实不会的,我在创建博文的时候就直接把标题和内容保存在ES中啦,读取的时候也是直接读取ES的,不会去取数据库,想当于多存储了一份数据(服务器内存硬盘小,好忧伤)。
3、操作ES的类
public interface TopicDao extends ElasticsearchRepository<Topic, Long>{
}
这里跟上一篇博文不同,这里继承的是ElasticsearchRepository,之间的差别后续再研究,毕竟我这个只是实战而已。
4、测试类MyController
/**
* ES控制类
* @author suibibk.com
*/
@RestController
public class MyController {
@Autowired
private TopicDao topicDao;
/**
* 保存博文
* @param request
* @return
*/
@RequestMapping("/add")
public String add(HttpServletRequest request) {
Long id = System.currentTimeMillis();
String title = request.getParameter("title");
String content = request.getParameter("content");
Topic topic =new Topic();
topic.setId(id);
topic.setTitle(title);
topic.setContent(content);
topicDao.save(topic);
System.out.println("topicid:"+id);
return id+"";
}
/**
* 根据ID查找
* @param request
* @return
*/
@RequestMapping("/selectById")
public Topic selectById(HttpServletRequest request) {
String id = request.getParameter("id");
//下面这里返回结果
Optional<Topic> t = topicDao.findById(Long.parseLong(id));
return t.get();
}
/**
* 根据用户的输入查找,虽然传的是content,这里只是名称定义而已,会搜索title和content都含有的记录
* @param request
* @return
*/
@RequestMapping("/selectBycontent")
public List<Topic> selectBycontent(HttpServletRequest request) {
String content = request.getParameter("content");
QueryStringQueryBuilder builder = new QueryStringQueryBuilder(content);
Iterable<Topic> searchResult = topicDao.search(builder);
Iterator<Topic> topics = searchResult.iterator();
List<Topic> list = new ArrayList<Topic>();
while(topics.hasNext()) {
list.add(topics.next());
}
return list;
}
/**
* 分页搜索,pageNum是从0开始的
* @param request
* @return
*/
@RequestMapping("/selectBycontentPage")
public List<Topic> selectBycontentPage(HttpServletRequest request) {
String pageNum = request.getParameter("pageNum");
int pageSize=2;
String content = request.getParameter("content");
QueryStringQueryBuilder builder = new QueryStringQueryBuilder(content);
Pageable pageable = PageRequest.of(Integer.parseInt(pageNum), pageSize);
// 分页参数
Iterable<Topic> searchResult = topicDao.search(builder,pageable);
Iterator<Topic> topics = searchResult.iterator();
List<Topic> list = new ArrayList<Topic>();
while(topics.hasNext()) {
list.add(topics.next());
}
System.out.println("数据大小:"+list.size());
return list;
}
}
这里主要注意是用如下的类来分页查询的。当然也还有别的类,以后再研究。
Pageable pageable = PageRequest.of(Integer.parseInt(pageNum), pageSize);
QueryStringQueryBuilder builder = new QueryStringQueryBuilder(content);
Iterable<Topic> searchResult = topicDao.search(builder,pageable);
5、启动程序测试
1.先启动该SpringBoot项目
这个当然不用说啦,右键运行即可。
2.添加几十条数据
访问链接:http://127.0.0.1:8080/add?title路漫漫其修远兮,吾将上下而求索&content=三生膳食 然后自救修改title和content添加几十条数据。每次添加完后都会返回一个id,就表示成功啦。
3、测试根据ID查询
根据上面添加数据的id,访问如下链接:
http://127.0.0.1:8080/selectById?id=1554284695241
将会返回如下内容:
{“id”:1554284695241,”title”:”路漫漫其修远兮,吾将上下而求索”,”content”:”三生三世”}
4、测试根据关键字搜索
访问如下链接:
http://127.0.0.1:8080/selectBycontent?content=的固
返回如下数据:
当然,上面的数据都是我在第二步插入的,我们可以知道,虽然传的是“的固”并不是一个组成短语,却仍然可以查询还有的或者固的内容来,真是强大。话说这里虽然只是实战,不讲原理,但是还是提一下原理是:倒排序。稍微了解的都可以知道,当然再保存的时候比较耗费时间和存储空间啦。没办法为了提高查询效率么,既然避免不了耗费更多的存储空间,只能尽量用算法优化降低存储空间的占用咯。
5、测试根据关键字分页查询
访问如下链接:
http://127.0.0.1:8080/selectBycontentPage?content=的固&pageNum=0
查询的是第一页,注意这里0才是第一页,返回如下数据:
可以看到只会返回第一页的数据,两条是因为我们代码里写死了一次查询两条,当我们把pageNum改为1的时候,返回的将会是第二页的数据,如下:
大家不要看中文内容,看到ID是有变化的。
6、GITHUB地址
https://github.com/suibibk/springboot-elasticsearch.git
总结
本博文基本上没有介绍任何原理性的东西,都只是为了实现全文检索目标的实战。后续会有博文慢慢研究讲解ES的原理。纯手打不易,转发请标注来源:
来源网站:随笔博客:https://www.suibibk.com/ ;IT小博客:https://www.suibibk.com/blog/538872310925361152