esay es官网 https://easy-es.cn/
源码:
链接:https://pan.baidu.com/s/1kZ4v4Of4MhHs7NKSVBOQNA
提取码:1111
<dependencies>
<dependency>
<groupId>com.ruoyigroupId>
<artifactId>ruoyi-common-elasticsearchartifactId>
dependency>
<dependency>
<groupId>cn.easy-esgroupId>
<artifactId>easy-es-annotationartifactId>
<version>1.0.2version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-mongodbartifactId>
dependency>
dependencies>
参考映射创建实体类:
{
"mappings":{
"properties":{
"id":{
"type":"long"
},
"publishTime":{
"type":"date"
},
"layout":{
"type":"integer"
},
"images":{
"type":"keyword",
"index": false
},
"staticUrl":{
"type":"keyword",
"index": false
},
"authorId": {
"type": "long"
},
"authorName": {
"type": "text"
},
"title":{
"type":"text",
"analyzer":"ik_smart"
},
"content":{
"type":"text",
"analyzer":"ik_smart"
}
}
}
}
一个类就够了:SearchArticleVo:
注意,title和content需要ik分词处理。title被搜索出来后,点击进入下一个界面会被作为参数传递,高亮的html标记被加入后无法通过地址栏传递,所以需要使用h_title作为高亮显示,注意注解中title和h_title的配置。映射后,高亮处理的title值会被映射到h_title,普通title不会被映射,即h_title为空。参见getH_title
package com.ruoyi.search.domain;
import cn.easyes.annotation.HighLight;
import cn.easyes.annotation.IndexField;
import cn.easyes.annotation.IndexId;
import cn.easyes.annotation.IndexName;
import cn.easyes.common.constants.Analyzer;
import cn.easyes.common.enums.FieldType;
import cn.easyes.common.enums.IdType;
import cn.easyes.common.utils.StringUtils;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
@IndexName
public class SearchArticleVo implements Serializable {
// 文章id
@IndexId(type = IdType.CUSTOMIZE)
private Long id;
// 文章标题
@HighLight(mappingField = "h_title",preTag = "",postTag = "")
@IndexField(fieldType = FieldType.TEXT, analyzer = Analyzer.IK_SMART, searchAnalyzer = Analyzer.IK_MAX_WORD)
private String title;
// 文章发布时间
@IndexField(fieldType = FieldType.DATE)
private Date publishTime;
// 文章布局
@IndexField(fieldType = FieldType.INTEGER)
private Integer layout;
// 封面
@IndexField(fieldType = FieldType.KEYWORD)
private String images;
// 作者id
@IndexField(fieldType = FieldType.LONG)
private Long authorId;
// 作者名词
@IndexField(fieldType = FieldType.TEXT)
private String authorName;
//静态url
@IndexField(fieldType = FieldType.KEYWORD)
private String staticUrl;
//文章内容
@IndexField(fieldType = FieldType.TEXT, analyzer = Analyzer.IK_SMART, searchAnalyzer = Analyzer.IK_MAX_WORD)
private String content;
@IndexField(exist = false)
private String h_title;
public String getH_title() {
return StringUtils.isBlank(this.h_title) ? this.title : h_title;
}
}
--- # elasticsearch 功能配置
# 文档地址: https://www.easy-es.cn/
# 更改包名需要去 EasyEsConfiguration 修改包扫描(后续版本支持配置文件读取)
easy-es:
banner: true
# 是否开启EE自动配置
enable: true
# es连接地址+端口 格式必须为ip:port,如果是集群则可用逗号隔开
address : 192.168.0.80:9200
# 默认为http
schema: http
# 注意ES建议使用账号认证 不使用会报警告日志
#如果无账号密码则可不配置此行
#username:
#如果无账号密码则可不配置此行
#password:
# 心跳策略时间 单位:ms
keep-alive-millis: 18000
# 连接超时时间 单位:ms
connectTimeout: 5000
# 通信超时时间 单位:ms
socketTimeout: 5000
# 请求超时时间 单位:ms
requestTimeout: 5000
# 连接请求超时时间 单位:ms
connectionRequestTimeout: 5000
# 最大连接数 单位:个
maxConnTotal: 100
# 最大连接路由数 单位:个
maxConnPerRoute: 100
global-config:
# 开启控制台打印通过本框架生成的DSL语句,默认为开启,测试稳定后的生产环境建议关闭,以提升少量性能
print-dsl: true
# 异步处理索引是否阻塞主线程 默认阻塞 数据量过大时调整为非阻塞异步进行 项目启动更快
asyncProcessIndexBlocking: true
db-config:
# 是否开启下划线转驼峰 默认为false
map-underscore-to-camel-case: true
# id生成策略 customize为自定义,id值由用户生成,比如取MySQL中的数据id,如缺省此项配置,则id默认策略为es自动生成
id-type: customize
# 字段更新策略 默认为not_null
field-strategy: not_null
# 默认开启,查询若指定了size超过1w条时也会自动开启,开启后查询所有匹配数据,若不开启,会导致无法获取数据总条数,其它功能不受影响.
enable-track-total-hits: true
# 数据刷新策略,默认为不刷新
refresh-policy: immediate
# 是否全局开启must查询类型转换为filter查询类型 默认为false不转换
enable-must2-filter: false
上面说的es mapper具体配置类为: search微服务需要引入kafka依赖: buildArticleToMinIO方法中调用生产者发消息
所以在微服务中创建mapper的位置要符合配置类:
由于使用了esay es,所以操作变得非常简单,没有定义service,直接在controller中完成即可:
init为初始化,postman执行一次即可。
search为搜索方法。注意条件:
PublishTimepackage com.ruoyi.search.controller;
import cn.easyes.core.biz.PageInfo;
import cn.easyes.core.conditions.LambdaEsQueryWrapper;
import com.ruoyi.common.dtos.ResponseResult;
import com.ruoyi.common.enums.AppHttpCodeEnum;
import com.ruoyi.common.satoken.utils.LoginHelper;
import com.ruoyi.search.domain.SearchArticleModel;
import com.ruoyi.search.domain.SearchArticleVo;
import com.ruoyi.search.domain.UserSearchDto;
import com.ruoyi.search.esmapper.SearchArticleMapper;
import com.ruoyi.search.mapper.ApArticleMapper;
import com.ruoyi.search.service.ApUserSearchService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@ConditionalOnProperty(value = "easy-es.enable", havingValue = "true")
@RestController
@RequestMapping
@RequiredArgsConstructor
public class ArticleSearchController {
private final ApArticleMapper apArticleMapper;
private final SearchArticleMapper searchArticleMapper;
private final ApUserSearchService apUserSearchService;
@PostMapping("/api/v1/article/search/search")
public ResponseResult search(@RequestBody UserSearchDto dto) throws IOException {
//todo 1.校验参数
if(dto == null || StringUtils.isBlank(dto.getSearchWords())){
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
}
//异步调用 保存搜索记录
//Long userId = LoginHelper.getUserId();
//if(userId != null){
apUserSearchService.insert(dto.getSearchWords(), 0L);
//}
//todo 2.1 封装关键字搜索条件,小于min_behot_time
LambdaEsQueryWrapper<SearchArticleVo> wrapper = new LambdaEsQueryWrapper<>();
wrapper
.lt(SearchArticleVo::getPublishTime,dto.getMinBehotTime())
.and(w->w.like(SearchArticleVo::getTitle, dto.getSearchWords()).or().like(SearchArticleVo::getContent,dto.getSearchWords()));
//todo 2.2. 分页查询
//wrapper.size(dto.getPageSize());
wrapper.orderByDesc(SearchArticleVo::getId);
PageInfo<SearchArticleVo> searchArticleVoPageInfo = searchArticleMapper.pageQuery(wrapper, 0, dto.getPageSize());
return ResponseResult.okResult(searchArticleVoPageInfo.getList());
}
@GetMapping("/api/v1/article/search/init")
public ResponseResult init() throws IOException {
//1.查询所有符合条件的文章数据
List<SearchArticleVo> searchArticleVos = apArticleMapper.loadArticleList();
for (SearchArticleVo searchArticleVo : searchArticleVos) {
searchArticleMapper.insert(searchArticleVo);
}
return ResponseResult.okResult(200,"初始化成功!");
}
}
3.创建文章后新增索引
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-stream-kafkaartifactId>
dependency>
search中创建消费者,新增索引:
其他还有一些mongo的代码,用于处理搜索记录和搜索自动提示,和原教程源码基本一致, 不再赘述。