上一篇博文,我们整合了一下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 {@Idprivate 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*/@RestControllerpublic class MyController {@Autowiredprivate 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
