Привыкайте писать вместе! Это 11-й день моего участия в «Новом ежедневном плане Nuggets · Апрельское задание по обновлению», нажмите, чтобы просмотреть подробности мероприятия .
Благодаря приведенному выше исследованию я считаю, что вы синхронизировали журналы, напечатанные springboot, с elasticsearch, а затем вам нужно запросить соответствующие данные в системном модуле в соответствии с условиями. Поскольку потребности блогера здесь относительно просты, а сценарии использования единичны, в качестве клиента используется старт, предоставляемый spring. Как интегрировать описано ниже.
1. Синтаксис запроса ElasticsearchTemplate
При использовании ElasticsearchTemplate вам нужно только освоить предоставленный API.Ниже приводится сводка часто используемых API-интерфейсов запросов для использования небольшими партнерами.
// 返回对象
Result<List<ActionLogVO>> result = new Result();
NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
BoolQueryBuilder bool = QueryBuilders.boolQuery();
//must为and的语法
//matchPhraseQuery为将type分词 然后将第二个参数匹配 可以模糊查询使用
bool.must(QueryBuilders.matchPhraseQuery("Type", "日志"));
//wildcardQuery模糊查询使用 但是字段需要未英文
bool.must(QueryBuilders.wildcardQuery("userName", "*admin*"));
//通过时间筛选
List<QueryBuilder> filters = bool.filter();
filters.add(QueryBuilders.rangeQuery("time").gte(sd.parse("2021-01-19 17:28:41"))
.lte(sd.parse("2021-01-19 17:28:43")));
//分页(第一个参数PageNum从第0页开始 第二个参数pageSize)
builder.withPageable(PageRequest.of(1, 10));
//排序
builder.withSort(SortBuilders.fieldSort("time").order(SortOrder.ASC));
// 构造查询条件
builder.withQuery(bool);
NativeSearchQuery query = builder.build();
Iterable<XXXVO> resultIter = XXXXService.search(query);
复制代码
2. Условный запрос
1. Измените файл pom
<!-- elasticsearch -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>2.3.7.RELEASE</version>
</dependency>
复制代码
2. Измените application.yml
spring:
elasticsearch:
rest:
uris: ip:9200
#上文安装时配置的账号密码
username: xxxx
password: xxxx
data:
elasticsearch:
repositories:
enabled: true
client:
reactive:
# username: xxx 这种写法是不对的
# password: xxx 这种写法是不对的
# endpoints: ip:9200 这种写法是不对的
use-ssl: false
复制代码
Уведомление:
- Конфигурационный адрес es должен быть указан в местоположении арендодателя, в противном случае по умолчанию он будет localhost: 9200. Если es установлен на других серверах, соединение не будет установлено.
- В отличие от конфигурации старой версии, номер открытого порта 9200.
3. Новый файл конфигурации
Если следующие файлы не будут добавлены, возникнет исключение java.lang.IllegalStateException: availableProcessors уже имеет значение [4], исключение [4] отклонено.
@Configuration
public class ElasticSearchConfig {
/**
* 防止netty的bug
* java.lang.IllegalStateException: availableProcessors is already set to [4], rejecting [4]
*/
@PostConstruct
void init() {
System.setProperty("es.set.netty.runtime.available.processors", "false");
}
}
复制代码
4. Написание интерфейса
В основном вызывайте API в ElasticsearchRestTemplate, подробное объяснение см. в комментариях ниже.
@Autowired
ElasticsearchRestTemplate elasticsearchTemplate;
@Log(operationName = "日志-查询登录日志")
@PostMapping("/selectLoginLog")
public Result<List<LoginLogVO>> selectLoginLog(@RequestBody LoginLogInputVO loginLogInputVO) throws ParseException {
// 日期格式化
SimpleDateFormat sd = new SimpleDateFormat(DateFormatEnum.YYYY_MM_DD_HH_MM_SS.getFormat());
// 返回对象
Result<List<LoginLogVO>> result = new Result();
NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
BoolQueryBuilder bool = QueryBuilders.boolQuery();
// 用户名不为空
if (!CommonUtil.isEmpty(loginLogInputVO.getUserName())) {
bool.must(QueryBuilders.wildcardQuery("userName", "*" + loginLogInputVO.getUserName() + "*"));
}
// 时间不为空
if (!CommonUtil.isEmpty(loginLogInputVO.getBeginTime()) && !CommonUtil.isEmpty(loginLogInputVO.getEndTime())) {
List<QueryBuilder> filters = bool.filter();
filters.add(QueryBuilders.rangeQuery("time")
.gte(sd.parse(loginLogInputVO.getBeginTime() + DateFormatEnum.BEGIN_HH_MM_SS.getFormat()))
.lte(sd.parse(loginLogInputVO.getEndTime() + DateFormatEnum.END_HH_MM_SS.getFormat())));
}
// 分页查询
if (!CommonUtil.isEmpty(loginLogInputVO.getPageSize()) && !CommonUtil.isEmpty(loginLogInputVO.getPageNum())) {
// 从第0页开始
builder.withPageable(PageRequest.of(loginLogInputVO.getPageNum() - 1, loginLogInputVO.getPageSize()));
}
builder.withSort(SortBuilders.fieldSort("time").order(SortOrder.ASC));
// 构造查询条件
builder.withQuery(bool);
NativeSearchQuery query = builder.build();
//查询的索引
IndexCoordinates indexCoordinates = IndexCoordinates.of("loginlog-*");
//执行查询
SearchHits<LoginLogVO> resultIter = elasticsearchTemplate.search(query, LoginLogVO.class, indexCoordinates);
// 格式化输出
List<LoginLogVO> resultList = new ArrayList<>();
List<SearchHit<LoginLogVO>> SearchHitList = resultIter.getSearchHits();
for (SearchHit<LoginLogVO> loginLogVOSearchHit : SearchHitList) {
resultList.add(loginLogVOSearchHit.getContent());
}
// 分页返回
if (!CommonUtil.isEmpty(loginLogInputVO.getPageSize()) && !CommonUtil.isEmpty(loginLogInputVO.getPageNum())) {
result.setTotal(resultIter.getTotalHits());
result.setPageNum(loginLogInputVO.getPageNum());
result.setPageSize(loginLogInputVO.getPageSize());
}
result.setData(resultList);
return result;
}
复制代码
Здесь индексы loginlog-* относятся ко всем индексам, начинающимся с loginlog-.
5. Класс сущности
1. Использование запроса клиента Elasticsearch
При выполнении метода elasticsearchTemplate.search требуется специальный класс сущности.
@Document(indexName = "loginlog-*", shards = 1, replicas = 0)
public class LoginLogVO {
@Id
private String id;
/**
* 信息
*/
@Field(type = FieldType.Keyword, analyzer = "ik_max_word")
private String message;
@Field(type = FieldType.Date, store = true, format = DateFormat.date_time)
private Date time;
}
复制代码
Объяснение следующее:
- @Document: указывает объект домена, сопоставленный с документом Elasticsearch, где indexName представляет имя индекса, shards — количество сегментов по умолчанию, а replicas — количество реплик по умолчанию.
- @Id: указывает идентификатор документа, и документ можно рассматривать как концепцию строки таблицы в mysql.
- @Field: тип поля в документе, где анализатор представляет тип токенизатора, формат представляет тип форматирования, а типы типов включают текст (тип символов, который будет сегментирован и индексирован), целое, длинное, дата, число с плавающей запятой, Двойное, логическое значение Подождите.
2. Введите ЗП
Для общего класса сущностей передайте параметры запроса.
public class LoginLogInputVO extends BaseEntity {
/**
* 用户账号
*/
private String userName;
/**
* 开始时间
*/
private String beginTime;
/**
* 结束时间
*/
private String endTime;
}
复制代码
Поскольку тип времени, согласованный передним и задним концами арендодателя, является строкой, необходимо преобразовать тип, а затем вернуть его.
6. Обратите внимание
elasticsearchTemplate может одновременно запрашивать только 10 000 элементов. Поэтому возвращать все страницы не рекомендуется, рекомендуется использовать следующий метод разбиения по страницам. Пожалуйста, обратитесь к Baidu.
3. Экспорт данных в пределах временного интервала
1. Написание интерфейса
@ApiOperation(value = "导出详细日志接口", notes = "导出详细日志接口")
@PostMapping("/exportDetailLog")
public void exportDetailLog(@ApiParam(name = "导出详细日志接口输入参数实体", value = "导出详细日志接口输入参数实体",
required = false) @RequestBody HandleDetailLogVO handleDetailLogVO) throws IOException, ParseException {
SimpleDateFormat sd = new SimpleDateFormat(DateFormatEnum.YYYY_MM_DD_HH_MM_SS.getFormat());
String beginTime = handleDetailLogVO.getBeginTime() + DateFormatEnum.BEGIN_HH_MM_SS.getFormat();
String endTime = handleDetailLogVO.getEndTime() + DateFormatEnum.END_HH_MM_SS.getFormat();
String path = handleDetailLogVO.getPath() + "/" + handleDetailLogVO.getBeginTime() + "-"
+ handleDetailLogVO.getEndTime() + ".txt";
// 根据时间查询
NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
BoolQueryBuilder bool = QueryBuilders.boolQuery();
List<QueryBuilder> filters = bool.filter();
//构建查询条件
filters.add(QueryBuilders.rangeQuery("time").gte(sd.parse(beginTime)).lte(sd.parse(endTime)));
builder.withQuery(bool);
NativeSearchQuery query = builder.build();
//查询的索引
IndexCoordinates indexCoordinates = IndexCoordinates.of("loginlog-*");
// 查询前1w条
SearchScrollHits<DetailLogVO> scroll =
elasticsearchTemplate.searchScrollStart(3000, query, DetailLogVO.class, indexCoordinates);
List<SearchHit<DetailLogVO>> resultList = new ArrayList<>();
while (scroll.hasSearchHits()) {
List<SearchHit<DetailLogVO>> searchHitList = scroll.getSearchHits();
resultList.addAll(searchHitList);
scroll = elasticsearchTemplate.searchScrollContinue(scroll.getScrollId(), 3000, DetailLogVO.class,
indexCoordinates);
}
// 导出为text流
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path, true), "utf-8"));
for (int i = 0; i < resultList.size(); i++) {
out.write(resultList.get(i).getContent().getMessage());
out.write("\r\n");
}
out.flush();
out.close();
// 删除索引
elasticsearchTemplate.delete(query, DetailLogVO.class, indexCoordinates);
}
复制代码
Примечание. Поскольку существует ограничение в 1 недельный запрос, запрос зацикливается. Но логи везде не могут превышать 8g.
2. Класс сущности
В основном это условие, что входной параметр содержит время запроса.
public class HandleDetailLogVO {
/**
* 结束时间
*/
@ApiModelProperty(value = "结束时间", name = "结束时间")
private String endTime;
/**
* 开始时间
*/
@ApiModelProperty(value = "开始时间", name = "开始时间")
private String beginTime;
/**
* 导出路径
*/
@ApiModelProperty(value = "导出路径", name = "导出路径")
private String path;
}
复制代码
4. Удалить данные за период времени
1. Написание интерфейса
Также удалите данные за период времени через API. Подробности смотрите в комментариях к коду.
@ApiOperation(value = "清除详细日志接口", notes = "清除详细日志接口")
@PostMapping("/clearDetailLog")
public void clearDetailLog(@ApiParam(name = "清除详细日志接口输入参数实体", value = "清除详细日志接口输入参数实体",
required = false) @RequestBody HandleDetailLogVO handleDetailLogVO) throws IOException, ParseException {
SimpleDateFormat sd = new SimpleDateFormat(DateFormatEnum.YYYY_MM_DD_HH_MM_SS.getFormat());
String beginTime = handleDetailLogVO.getBeginTime() + DateFormatEnum.BEGIN_HH_MM_SS.getFormat();
String endTime = handleDetailLogVO.getEndTime() + DateFormatEnum.END_HH_MM_SS.getFormat();
// 根据时间查询
NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
BoolQueryBuilder bool = QueryBuilders.boolQuery();
List<QueryBuilder> filters = bool.filter();
filters.add(QueryBuilders.rangeQuery("time").gte(sd.parse(beginTime)) .lte(sd.parse(endTime)));
builder.withQuery(bool);
//构建查询条件
NativeSearchQuery query = builder.build();
//指定删除索引的名称
IndexCoordinates indexCoordinates = IndexCoordinates.of("datalog-*");
// 调用API删除索引
elasticsearchTemplate.delete(query, DetailLogVO.class, indexCoordinates);
}
复制代码
2. Класс сущности
Входная сущность, содержащая условия запроса.
public class HandleDetailLogVO {
/**
* 结束时间
*/
@ApiModelProperty(value = "结束时间", name = "结束时间")
private String endTime;
/**
* 开始时间
*/
@ApiModelProperty(value = "开始时间", name = "开始时间")
private String beginTime;
}
复制代码