当添加一个文档时,文档存放在mongodb中(数据库),同时将文档存放在elasticsearch中用于根据文档名称和内容进行全文检索。
需求分析:查询文档列表
① 当选择多个分类时,需要查询这些分类下的文档,没有选择分类时,查询全部文档。
② 当输入查询关键字时,需要根据文档的名称和文档的内容进行全文检索。
③ 当选择文档标签时,需要精确匹配标签,标签可以选择多个。
④ 当选择最近更新时间时,需要根据最近更新时间查询。
根据更新时间查询时,如果是根据最近(24小时,30天等)查询:请求url
GET http://10.64.2.27:8129/ngsoc/KNOWLEDGE/api/v1/docs? categoryIds=61669a53b8238341868cb2f2&categoryIds=616686c5057866695bda3c23 &keyword=演讲&tag=历史记录&tag=演讲系列&timeScope=last7d&start=1&limit=5
根据更新时间查询时,如果是根据自定义时间查询:请求url
GET http://10.64.2.27:8129/ngsoc/KNOWLEDGE/api/v1/docs? categoryIds=61669a53b8238341868cb2f2&categoryIds=616686c5057866695bda3c23 &keyword=演讲&tag=历史记录&tag=演讲系列&timeScope=1635696000:1635868799:custom_time&start=1&limit=5
| 参数名 | 描述 | 类型 | 是否必填 | 备注 |
|---|---|---|---|---|
| categoryIds | 分类id集合 | array | 否 | 获取指定分类下的文档列表,没有选择分类时,分页显示所有文档,Set集合 |
| keyword | 搜索关键字 | String | 否 | 根据文档名称和文档内容进行全文搜索 |
| tags | 知识文档标签 | array | 否 | 根据知识文档标签查询 |
| timeScope | 时间区间 | Object | 否 | 根据最近更新时间进行查询,last24h(最近24小时),last7d(最近7天),last14d(最近14天),last30d(最近30天),custom_time(自定义时间段) |
| start | 当前页的起始行 | int | 否 | 默认值为0 |
| limit | 每页显示数量 | int | 否 | 默认值为5 |
@Slf4j
@Service
public class ElasticSearchImpl implements ElasticSearchService, CommonConstant {
@Autowired
private RestHighLevelClient restHighLevelClient;
private SearchRequest buildSearchRequest(DocSearchReqVo docSearchReqVo) {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
// 根据分类查询
List categoryIds = docSearchReqVo.getCategoryIds();
if (!CollectionUtils.isEmpty(categoryIds)) {
boolQueryBuilder.filter(QueryBuilders.termsQuery("categoryId", categoryIds));
}
// 对content和name采用全文检索
String keyword = docSearchReqVo.getKeyword();
if (StringUtils.isNotEmpty(keyword)) {
boolQueryBuilder.must(QueryBuilders.multiMatchQuery(keyword, "content", "name"));
}
// 对tags采用精确查询
List tags = docSearchReqVo.getTags();
if (!CollectionUtils.isEmpty(tags)) {
boolQueryBuilder.must(QueryBuilders.termsQuery("tags", tags));
}
// 根据updateTime的时间区间查询
TimeRange time = TimeUtil.getTimeRange(docSearchReqVo.getTimeScope());
if (time != null) {
// 校验并初始化查询参数
TimeUtil.formatAndCheckQueryParam(time, new Date());
Long timeFrom = time.getTimeFrom();
Long timeTo = time.getTimeTo();
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("updateTime").from(timeFrom).to(timeTo);
boolQueryBuilder.filter(rangeQueryBuilder);
}
searchSourceBuilder.query(boolQueryBuilder);
// 分页和排序
searchSourceBuilder.from(docSearchReqVo.getStart());
searchSourceBuilder.size(docSearchReqVo.getLimit());
searchSourceBuilder.sort("updateTime", SortOrder.DESC);
return new SearchRequest(new String[] { ELASTICSEARCH_KNOWLEDGE_INDEX }, searchSourceBuilder);
}
}
3. 根据updateTime的时间区间查询
① 定义枚举类:
@AllArgsConstructor
@Getter
public enum TimeScopeEnum {
LAST_24_HOURS("last24h", 1),
LAST_7_DAYS("last7d", 7),
LAST_14_DAYS( "last14d", 14),
LAST_30_DAYS("last30d", 30);
private final String name;
private final Integer value;
}
② 定义时间区间类TimeRange:
@Data
public class TimeRange {
@ApiModelProperty(value = "起始时间")
private Long timeFrom;
@ApiModelProperty(value = "结束时间")
private Long timeTo;
@ApiModelProperty(value = "传入的查询时间")
private String timeRange;
}
③ 将前端传过来的时间参数数据封装成TimeRange对象:
自定义:timeScope=1635696000:1635868799:custom_time 最近更新时间:timeScope=last7d
public class TimeUtil implements CommonConstant {
public static TimeRange getTimeRange(String timeScope) {
TimeRange time = null;
if (StringUtils.isNotEmpty(timeScope)) {
time = new TimeRange();
String[] split = timeScope.split(":");
if (split.length == 1) {
// 说明不是自定义时间,将其封装成timeRange对象
time = TimeUtil.fetchTimeRangeByObj(timeScope);
} else {
time.setTimeFrom(Long.valueOf(split[0]));
time.setTimeTo(Long.valueOf(split[1]));
time.setTimeRange(split[2]);
}
}
return time;
}
public static TimeRange fetchTimeRangeByObj(Object alarmRange) {
TimeRange timeRange = new TimeRange();
if (alarmRange instanceof String) {
timeRange.setTimeRange((String) alarmRange);
} else {
timeRange = new ObjectMapper().convertValue(alarmRange, new TypeReference<>() {
});
}
return timeRange;
}
}
④ 校验并初始化TimeRange对象的时间参数数据:
public class TimeUtil implements CommonConstant {
public static void formatAndCheckQueryParam(TimeRange timeRange, Date now) {
String rangeTimeRange = timeRange.getTimeRange();
// 查询过去30天的文档,包括当天的文档
if (TimeScopeEnum.LAST_30_DAYS.getName().equals(rangeTimeRange)) {
// 计算开始时间
Date temp = DateUtils.addDays(now, -(THIRTY - 1));
Date from = DateUtil.timeStr2Date(DateUtil.date2Str(temp, YYYYMMDD), YYYYMMDDHHMMSS);
// 设置开始时间
timeRange.setTimeFrom(from.getTime());
// 设置结束时间
timeRange.setTimeTo(now.getTime());
return;
}
// 查询过去14天的文档,包括当天的文档
if (TimeScopeEnum.LAST_14_DAYS.getName().equals(rangeTimeRange)) {
Date temp = DateUtils.addDays(now, -(FOERTRRN - 1));
Date from = DateUtil.timeStr2Date(DateUtil.date2Str(temp, YYYYMMDD), YYYYMMDDHHMMSS);
timeRange.setTimeFrom(from.getTime());
timeRange.setTimeTo(now.getTime());
return;
}
// 查询过去7天的文档,包括当天的文档
if (TimeScopeEnum.LAST_7_DAYS.getName().equals(rangeTimeRange)) {
Date temp = DateUtils.addDays(now, -(SEVEN - 1));
Date from = DateUtil.timeStr2Date(DateUtil.date2Str(temp, YYYYMMDD), YYYYMMDDHHMMSS);
timeRange.setTimeFrom(from.getTime());
timeRange.setTimeTo(now.getTime());
return;
}
// 查询过去24小时文档
if (TimeScopeEnum.LAST_24_HOURS.getName().equals(rangeTimeRange)) {
Date temp = DateUtils.addHours(now, -(TWENTY_FOUR - 1));
Date from = DateUtil.timeStr2Date(DateUtil.date2Str(temp, YYYYMMDDHH), YYYYMMDDHHMMSS);
timeRange.setTimeFrom(from.getTime());
timeRange.setTimeTo(now.getTime());
return;
}
// 自定义查询范围
if (ALARM_OVERVIEW_QUERY_SELF.equals(rangeTimeRange)) {
verifiyTimeRange(timeRange);
}
}
private static void verifiyTimeRange(TimeRange timeRange) {
Long start = timeRange.getTimeFrom();
Long end = timeRange.getTimeTo();
// 起始时间和结束时间任意一个为空
if (Objects.isNull(start) || Objects.isNull(end)) {
String msg = I18nUtils.i18n("query.time.no.empty");
throw new CommonException(msg);
}
}
}
⑤ 根据时间区间查询:
@Slf4j
@Service
public class ElasticSearchImpl implements ElasticSearchService, CommonConstant {
@Autowired
private RestHighLevelClient restHighLevelClient;
private SearchRequest buildSearchRequest(DocSearchReqVo docSearchReqVo) {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
// 根据updateTime的时间区间查询
TimeRange time = TimeUtil.getTimeRange(docSearchReqVo.getTimeScope());
if (time != null) {
// 校验并初始化查询参数
TimeUtil.formatAndCheckQueryParam(time, new Date());
Long timeFrom = time.getTimeFrom();
Long timeTo = time.getTimeTo();
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("updateTime").from(timeFrom).to(timeTo);
boolQueryBuilder.filter(rangeQueryBuilder);
}
searchSourceBuilder.query(boolQueryBuilder);
return new SearchRequest(new String[] { ELASTICSEARCH_KNOWLEDGE_INDEX }, searchSourceBuilder);
}
}



