分布式搜索引擎
结构化、非结构化、地理位置。
搜索引擎搜索:1,提交数据到搜索引擎(它再存一份,它还会建立索引提高效率)
es中的索引-----》mysql中的数据库database
es中的类型----》mysql中的表table
es中的文档(数据结构为json)-----》msql中的一张表中的一行数据row
json当中的每一个属性叫字段------》mysql中的一列col
从6.0之后
es的索引----》mysql的表, 类型逐渐废弃
多台服务器构成集群,集群中的每台服务器称为节点,一个索引(一个表)数据很多,对索引进一步划分存储,并发能力提高,副本是对分片的备份。
修改配置
配置环境变量
将其bin目录加到系统的path下
下载分词postman
开启es
直接点击bin下面的bat
查看es集群的健康状态
查看结点
单节点
查看有多少索引
yellow不是最健康的状态,没有备份
删除索引
建立索引
插入数据
查询数据
改数据直接在body里面修改
删除数据
搜索
先插入几条数据
搜索
SpringBoot整合Elasticsearchorg.springframework.boot spring-boot-starter-data-elasticsearch
解决redis和es的netty冲突问题
管理bean的生命周期,管理bean初始化的方法
@PostConstruct //解决netty启动冲突问题
public void init(){
System.setProperty("es.set.netty.runtime.available.processors","false");
}
将贴子存到es服务器里面,我们去搜索帖子。
配置帖子表和es索引的对应关系,每个字段对应什么样的类型,注解配置
将实体数据和es里面的数据进行映射,映射到那个索引,那个字段,那个分区,那个副本
分词器,拆分更可能多的词,用最聪明的分词器
dao里面定义接口
@Mapper是mybatis专用注解,@Repository是数据访问层使用的注解。继承spring默认接口es,加上泛型实体类和主键类型
创建测试类测试
从mysql数据库中取数据,再将其转存到es中。
先打开postman里面有没有帖子相关内容(服务器里面有哪些索引)
添加数据
(前提Kafka,zookeeper,es都启动)
查数据
Page不是我们自己写的类,是别人封装的
搜索测试类
@Test
public void testSearchTemplate(){
SearchQuery searchQuery=new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.multiMatchQuery("互联网寒冬","title","content"))//搜索条件(即从title和content)
.withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC))//排序条件(按照type是否置顶,score帖子分值,时间依次排序)
.withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC))
.withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
.withPageable(PageRequest.of(0,10))//分页条件
.withHighlightFields(
new HighlightBuilder.Field("title").preTags("").postTags(""),
new HighlightBuilder.Field("content").preTags("").postTags("")
).build();//哪些词高亮显示(前后置标签)
Page page = elasticTemplate.queryForPage(searchQuery, DiscussPost.class, new SearchResultMapper() {
@Override
public AggregatedPage mapResults(SearchResponse response, Class aClass, Pageable pageable) {
SearchHits hits=response.getHits();
if(hits.getTotalHits()<=0){
return null;
}
//遍历命中的数据
List list=new ArrayList<>();
for (SearchHit hit : hits) {
DiscussPost post=new DiscussPost();
//将数据包装到实体类返回(在hit里将json封装成了map)
String id = hit.getSourceAsMap().get("id").toString();
post.setId(Integer.valueOf(id));//将字符串id转为数字
String userId = hit.getSourceAsMap().get("userId").toString();
post.setUserId(Integer.valueOf(userId));
//获得原始的title,content(可能里面没有关键词在content里)
String title = hit.getSourceAsMap().get("title").toString();
post.setTitle(title);
String content = hit.getSourceAsMap().get("content").toString();
post.setContent(content);
String status = hit.getSourceAsMap().get("status").toString();
post.setStatus(Integer.valueOf(status));
//日期是long类型的字符串,将其先转为long再转为日期
String createTime = hit.getSourceAsMap().get("createTime").toString();
post.setCreateTime(new Date(Long.valueOf(createTime)));
//处理高亮显示的结果
//(获得高亮显示的内容)
HighlightField titleField = hit.getHighlightFields().get("title");
if(titleField!=null){
//不为空,重新设置title(只要第一个高亮部分)
post.setTitle(titleField.getFragments()[0].toString());
}
HighlightField contentField = hit.getHighlightFields().get("content");
if(contentField!=null){
post.setContent(contentField.getFragments()[0].toString());
}
list.add(post);
}
return new AggregatedPageImpl(list,pageable,
hits.getTotalHits(),response.getScrollId(),hits.getMaxScore());
}
});
//多少行,多少页,当前在哪一页,当前页显示了多少条数据
System.out.println(page.getTotalElements());
System.out.println(page.getTotalPages());
System.out.println(page.getNumber());
System.out.println(page.getSize());
for (DiscussPost post : page) {
System.out.println(post);
}
}
开发社区搜索功能
//搜索表现层(传入关键词,分页自己封装的page)
//get请求参数不能用请求体来传,用路径后加?,用路径中的某一级来传
//search?keyword=xxx
@RequestMapping(path = "/search",method = RequestMethod.GET)
public String search(String keyword, Page page, Model model){
//搜索帖子集合,es里面的当前页是从0开始,我们封装的page是从1开始,减1
org.springframework.data.domain.Page discussPosts =
elasticsearchService.searchDiscussPost(keyword, page.getCurrent() - 1, page.getLimit());
//聚合需要的数据
List



