代码补全1
This commit is contained in:
parent
7d0db17340
commit
93512b68d8
|
@ -83,6 +83,9 @@ public class AlbumInfoApiController {
|
|||
* 查询当前用户专辑列表
|
||||
* @return
|
||||
*/
|
||||
|
||||
|
||||
/*这个接口是为了在声音列表中获取当前用户的所有专辑 有一个下拉框 在那里能显示内容*/
|
||||
@GuiGuLogin
|
||||
@Operation(summary = "查询当前用户专辑列表")
|
||||
@GetMapping("/albumInfo/findUserAllAlbumList")
|
||||
|
|
|
@ -18,6 +18,7 @@ public class FileUploadApiController {
|
|||
|
||||
@Autowired
|
||||
private FileUploadService fileUploadService;
|
||||
//这个接口是将文件上传到minio上
|
||||
@Operation(summary = "上传文件")
|
||||
@PostMapping("/fileUpload")
|
||||
public Result<String> fileUpload(@RequestParam("file") MultipartFile file) throws IOException {
|
||||
|
|
|
@ -26,6 +26,7 @@ public class VodConstantProperties {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
//文件上传到腾讯云服务
|
||||
@Bean
|
||||
public VodUploadClient vodUploadClient() {
|
||||
return new VodUploadClient(secretId, secretKey);
|
||||
|
|
|
@ -41,6 +41,7 @@ public class BaseCategoryServiceImpl extends ServiceImpl<BaseCategory1Mapper, Ba
|
|||
//创建一个新的List对象
|
||||
List<JSONObject> returnList = new ArrayList<>();
|
||||
//2.查询所有分类数据-查询视图即可 共计401条记录
|
||||
//获取了全部的分组数据 将其封装到了一个<basecategoryview>的集合中
|
||||
List<BaseCategoryView> allCategoryList = baseCategoryViewMapper.selectList(null);
|
||||
//3.处理一级分类数据
|
||||
//3.1 对所有分类集合列表进行分组按照1级分类ID进行分组 得到Map<分组ID,一级分类列表>
|
||||
|
|
|
@ -4,6 +4,7 @@ package com.atguigu.tingshu.album.service.impl;
|
|||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import com.atguigu.tingshu.album.config.MinioConstantProperties;
|
||||
import com.atguigu.tingshu.album.service.AuditService;
|
||||
import com.atguigu.tingshu.album.service.FileUploadService;
|
||||
import com.atguigu.tingshu.common.execption.GuiguException;
|
||||
import io.minio.MinioClient;
|
||||
|
@ -25,6 +26,8 @@ public class FileUploadServiceImpl implements FileUploadService {
|
|||
|
||||
@Autowired
|
||||
private MinioConstantProperties minioConstantProperties;
|
||||
@Autowired
|
||||
private AuditService auditService;
|
||||
@Override
|
||||
public String fileUpload(MultipartFile file) throws IOException {
|
||||
|
||||
|
@ -32,21 +35,31 @@ public class FileUploadServiceImpl implements FileUploadService {
|
|||
//1.业务校验 检验图片是否合法
|
||||
BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
|
||||
if (bufferedImage == null) {
|
||||
throw new GuiguException(500,"上传文件类型错误");
|
||||
throw new GuiguException(500, "图片文件格式不合法");
|
||||
}
|
||||
//2.检查图片上传的大小是否合理
|
||||
|
||||
//2.业务校验:校验图片文件大小是否合法 业务限制避免上传高清图片
|
||||
int width = bufferedImage.getWidth();
|
||||
int height = bufferedImage.getHeight();
|
||||
if (width > 900 || height > 900) {
|
||||
throw new GuiguException(500,"上传图片过大");
|
||||
throw new GuiguException(500, "图片文件大小不合法");
|
||||
}
|
||||
|
||||
//TODO 对图片进行审核
|
||||
String suggestion = auditService.auditImage(file);
|
||||
if ("block".equals(suggestion) || "review".equals(suggestion)) {
|
||||
throw new GuiguException(500, "图片违规");
|
||||
}
|
||||
|
||||
//3.将图片文件上传MINIO 规范:日期/文件唯一命名.后缀
|
||||
//3.1 生成日期作为文件夹名称
|
||||
String folderName = DateUtil.today();
|
||||
|
||||
//3.2 生成文件唯一名称
|
||||
String extName = FileUtil.extName(file.getOriginalFilename());
|
||||
String objectName = "/" + folderName + "/" + UUID.randomUUID().toString() + "." + extName;
|
||||
//3.上传文件
|
||||
|
||||
//3.3 上传文件
|
||||
try {
|
||||
minioClient.putObject(
|
||||
PutObjectArgs.builder().bucket(minioConstantProperties.getBucketName()).object(objectName).stream(
|
||||
|
@ -58,7 +71,6 @@ public class FileUploadServiceImpl implements FileUploadService {
|
|||
throw new GuiguException(500, "上传文件到MINIO失败");
|
||||
}
|
||||
|
||||
|
||||
//4.拼接MINIO文件在线地址
|
||||
return minioConstantProperties.getEndpointUrl() + "/" + minioConstantProperties.getBucketName() + objectName;
|
||||
}
|
||||
|
|
|
@ -76,7 +76,10 @@ public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo
|
|||
trackInfoMapper.insert(trackInfo);
|
||||
|
||||
//2.2.4 TODO 调用内容审核接口,发起内容审核,更新审核任务ID
|
||||
//审核标题和简介
|
||||
String text = trackInfo.getTrackTitle() + trackInfo.getTrackIntro();
|
||||
//获得一个标识 pass或者block review等字符 这样可以分辨出来是不是通过
|
||||
//将trackInfo中的状态设置为已通过或其他
|
||||
String suggestion = auditService.auditText(text);
|
||||
if ("pass".equals(suggestion)) {
|
||||
trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
|
||||
|
@ -118,7 +121,13 @@ public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo
|
|||
trackStat.setStatNum(statNum);
|
||||
trackStatMapper.insert(trackStat);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页条件查询当前用户声音列表
|
||||
*
|
||||
* @param pageInfo 分页对象
|
||||
* @param trackInfoQuery 查询条件
|
||||
* @return 分页对象
|
||||
*/
|
||||
@Override
|
||||
public Page<TrackListVo> findUserTrackPage(Page<TrackListVo> pageInfo, TrackInfoQuery trackInfoQuery) {
|
||||
return trackInfoMapper.findUserTrackPage(pageInfo, trackInfoQuery);
|
||||
|
|
|
@ -34,6 +34,7 @@ public class VodServiceImpl implements VodService {
|
|||
public Map<String, String> uploadTrack(MultipartFile file) {
|
||||
//1.首先将上传文件保存到本地临时文件夹中 后期采取定时任务去清理临时文件夹
|
||||
try {
|
||||
//在这个vodConstantProperties.getTempPath里改写自己的临时缓存地址
|
||||
String tempPath = UploadFileUtil.uploadTempPath(vodConstantProperties.getTempPath(), file);
|
||||
//2.上传到腾讯云点播平台
|
||||
//2.1 构造上传请求对象
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
package com.atguigu.tingshu.search.api;
|
||||
|
||||
import com.atguigu.tingshu.common.result.Result;
|
||||
import com.atguigu.tingshu.query.search.AlbumIndexQuery;
|
||||
import com.atguigu.tingshu.search.service.SearchService;
|
||||
import com.atguigu.tingshu.vo.search.AlbumSearchResponseVo;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Tag(name = "搜索专辑管理")
|
||||
@RestController
|
||||
|
@ -40,6 +39,21 @@ public class SearchApiController {
|
|||
searchService.lowerAlbum(albumId);
|
||||
return Result.ok();
|
||||
}
|
||||
/**
|
||||
* 站内多条件检索
|
||||
*
|
||||
* @param albumIndexQuery
|
||||
* @return
|
||||
*/
|
||||
//传出的是AlbumSearchResponseVo 这个vo类
|
||||
// 前端传过来的是AlbumIndexQuery这个实体类
|
||||
@Operation(summary = "站内多条件检索")
|
||||
@PostMapping("/albumInfo")
|
||||
public Result<AlbumSearchResponseVo> search(@RequestBody AlbumIndexQuery albumIndexQuery){
|
||||
AlbumSearchResponseVo albumSearchResponseVo=searchService.search(albumIndexQuery);
|
||||
return Result.ok(albumSearchResponseVo);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
package com.atguigu.tingshu.search.service;
|
||||
|
||||
import com.atguigu.tingshu.query.search.AlbumIndexQuery;
|
||||
import com.atguigu.tingshu.vo.search.AlbumSearchResponseVo;
|
||||
|
||||
public interface SearchService {
|
||||
|
||||
|
||||
void upperAlbum(Long albumId);
|
||||
|
||||
void lowerAlbum(Long albumId);
|
||||
|
||||
AlbumSearchResponseVo search(AlbumIndexQuery albumIndexQuery);
|
||||
}
|
||||
|
|
|
@ -4,23 +4,35 @@ import cn.hutool.core.bean.BeanUtil;
|
|||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
||||
import co.elastic.clients.elasticsearch._types.SortOrder;
|
||||
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
|
||||
import co.elastic.clients.elasticsearch.core.SearchRequest;
|
||||
import co.elastic.clients.elasticsearch.core.SearchResponse;
|
||||
import co.elastic.clients.elasticsearch.core.search.Hit;
|
||||
import com.atguigu.tingshu.album.AlbumFeignClient;
|
||||
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
|
||||
import com.atguigu.tingshu.model.album.AlbumInfo;
|
||||
import com.atguigu.tingshu.model.album.BaseCategoryView;
|
||||
import com.atguigu.tingshu.model.search.AlbumInfoIndex;
|
||||
import com.atguigu.tingshu.model.search.AttributeValueIndex;
|
||||
import com.atguigu.tingshu.query.search.AlbumIndexQuery;
|
||||
import com.atguigu.tingshu.search.repository.AlbumInfoIndexRepository;
|
||||
import com.atguigu.tingshu.search.service.SearchService;
|
||||
import com.atguigu.tingshu.user.client.UserFeignClient;
|
||||
import com.atguigu.tingshu.vo.search.AlbumInfoIndexVo;
|
||||
import com.atguigu.tingshu.vo.search.AlbumSearchResponseVo;
|
||||
import com.atguigu.tingshu.vo.user.UserInfoVo;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -40,6 +52,8 @@ public class SearchServiceImpl implements SearchService {
|
|||
private AlbumFeignClient albumFeignClient;
|
||||
@Autowired
|
||||
private UserFeignClient userFeignClient;
|
||||
@Autowired
|
||||
private ElasticsearchClient elasticsearchClient;
|
||||
|
||||
|
||||
@Override
|
||||
|
@ -122,4 +136,165 @@ public class SearchServiceImpl implements SearchService {
|
|||
public void lowerAlbum(Long albumId) {
|
||||
albumInfoIndexRepository.deleteById(albumId);
|
||||
}
|
||||
|
||||
|
||||
/*可以将这个想成kibana中开发工具哪个 buildDsl可以想象成左侧我们写的数据 我们在写
|
||||
buildDSL这个方法的时候就是在拼接这个dsl语句
|
||||
第二步执行检索的时候就是在执行那个播放键
|
||||
第三步就是在看右边的数据 我们要对这个数据进行分析*/
|
||||
@Override
|
||||
public AlbumSearchResponseVo search(AlbumIndexQuery albumIndexQuery) {
|
||||
//一、构建检索请求对象
|
||||
try {
|
||||
SearchRequest searchRequest = this.buildDSL(albumIndexQuery);
|
||||
//打印出来DSL
|
||||
System.err.println("本次检索DSL,复制到Kibana验证:");
|
||||
System.err.println(searchRequest.toString());
|
||||
//二、执行检索
|
||||
SearchResponse<AlbumInfoIndex> searchResponse = elasticsearchClient.search(searchRequest, AlbumInfoIndex.class);
|
||||
//三.分析数据
|
||||
return this.parseResult(searchResponse, albumIndexQuery);
|
||||
} catch (IOException e) {
|
||||
log.error("执行检索失败:{}", e.getMessage());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static final String INDEX_NAME = "albuminfo";
|
||||
|
||||
|
||||
//创建一个构建器
|
||||
private SearchRequest buildDSL(AlbumIndexQuery albumIndexQuery) {
|
||||
//创建一个构建器
|
||||
SearchRequest.Builder builder = new SearchRequest.Builder();
|
||||
//创建一个索引库,名字为albuminfo
|
||||
builder.index(INDEX_NAME);
|
||||
|
||||
//3.逐项封装请求体参数
|
||||
//3.1 设置请求体参数"query"查询条件
|
||||
//3.1.1 创建bool查询组合三大查询条件
|
||||
BoolQuery.Builder allConditionBoolQueryBuilder = new BoolQuery.Builder();
|
||||
//3.1.2 处理关键字查询条件
|
||||
String keyword = albumIndexQuery.getKeyword();
|
||||
if (StringUtils.isNotBlank(keyword)) {
|
||||
allConditionBoolQueryBuilder.must(m -> m.match(m1 -> m1.field("albumTitle").query(keyword)));
|
||||
}
|
||||
//3.1.3 处理1,2,3级分类过滤条件
|
||||
Long category1Id = albumIndexQuery.getCategory1Id();
|
||||
if (category1Id != null) {
|
||||
allConditionBoolQueryBuilder.filter(f -> f.term(t -> t.field("category1Id").value(category1Id)));
|
||||
}
|
||||
Long category2Id = albumIndexQuery.getCategory2Id();
|
||||
if (category2Id != null) {
|
||||
allConditionBoolQueryBuilder.filter(f -> f.term(t -> t.field("category2Id").value(category2Id)));
|
||||
}
|
||||
Long category3Id = albumIndexQuery.getCategory3Id();
|
||||
if (category3Id != null) {
|
||||
allConditionBoolQueryBuilder.filter(f -> f.term(t -> t.field("category3Id").value(category3Id)));
|
||||
}
|
||||
//3.1.4 处理多组标签过滤条件 标签id:标签值id
|
||||
List<String> attributeList = albumIndexQuery.getAttributeList();
|
||||
if (CollUtil.isNotEmpty(attributeList)) {
|
||||
//我们就循环遍历这个List集合 List集合每一个都是一个(标签值:标签内容值)的组合对
|
||||
for (String attribute : attributeList) {
|
||||
String[] split = attribute.split(":");
|
||||
if (split != null && split.length == 2) {
|
||||
allConditionBoolQueryBuilder.filter(f -> f.nested(
|
||||
n -> n.path("attributeValueIndexList")
|
||||
.query(q-> q.bool(b->b.must(m->m.term(t->t.field("attributeValueIndexList.attributeId").value(split[0])))
|
||||
.must(m->m.term(t->t.field("attributeValueIndexList.valueId").value(split[1])))))));
|
||||
}
|
||||
}
|
||||
}
|
||||
//这个是将bool查询变成query 方便到时候查询
|
||||
builder.query(allConditionBoolQueryBuilder.build()._toQuery());
|
||||
|
||||
//3.2 设置请求体参数"from","size"分页
|
||||
//直接从前端返过来数据拿出来,将总数-1乘size,获取总数
|
||||
Integer pageNo = albumIndexQuery.getPageNo();
|
||||
Integer pageSize = albumIndexQuery.getPageSize();
|
||||
int from = (pageNo - 1) * pageSize;
|
||||
builder.from(from).size(pageSize);
|
||||
//3.3 设置请求体参数"highlight"高亮
|
||||
|
||||
//如果关键词不为空 那么我们就套写highlight内的数据
|
||||
//builder.highlight说明是高亮 内容接着嵌套 h.fields里面是下一层的fields 再h1就是fields里面的
|
||||
//preTags和postTags
|
||||
if (StringUtils.isNotBlank(keyword)) {
|
||||
builder.highlight(h -> h.fields("albumTitle", h1 -> h1.preTags("<span style='color:red'>").postTags("</span>")));
|
||||
}
|
||||
//3.4 设置请求体参数"sort"排序 形式:高亮字段(1,2,3):排序规则
|
||||
//具体规则是"排序(综合排序[1:desc] 播放量[2:desc] 发布时间[3:desc];asc:升序 desc:降序)"
|
||||
//从传过来的前端数据中我们将拿到排序字段,先判断是否为空 如果不为空我们就将其根据冒号分割
|
||||
//分割成一个数组 0号索引是排序字段 1号索引是排序方向
|
||||
String order = albumIndexQuery.getOrder();
|
||||
if (StringUtils.isNotBlank(order)) {
|
||||
String[] split = order.split(":");
|
||||
if (split != null && split.length == 2) {
|
||||
String orderField = "";
|
||||
switch (split[0]) {
|
||||
case "1":
|
||||
orderField = "hotScore";
|
||||
break;
|
||||
case "2":
|
||||
orderField = "playStatNum";
|
||||
break;
|
||||
case "3":
|
||||
orderField = "createTime";
|
||||
break;
|
||||
}
|
||||
String finalorderField = orderField;
|
||||
//判断一下是升序还是降序
|
||||
SortOrder sortOrder = split[1].equals("asc") ? SortOrder.Asc : SortOrder.Desc;
|
||||
builder.sort(s -> s.field(f -> f.field(finalorderField).order(sortOrder)));
|
||||
}
|
||||
}
|
||||
//3.5 设置请求体参数"_source"指定字段响应
|
||||
builder.source(s -> s.filter(f -> f.excludes("attributeValueIndexList",
|
||||
"hotScore",
|
||||
"commentStatNum",
|
||||
"buyStatNum",
|
||||
"subscribeStatNum",
|
||||
"announcerName")));
|
||||
//4.基于检索对象构建器对象返回实际检索请求对象
|
||||
return builder.build();
|
||||
}
|
||||
private AlbumSearchResponseVo parseResult(SearchResponse<AlbumInfoIndex> searchResponse, AlbumIndexQuery albumIndexQuery) {
|
||||
//1.创建响应VO对象
|
||||
AlbumSearchResponseVo vo = new AlbumSearchResponseVo();
|
||||
//2.封装VO中分页相关四项属性
|
||||
//2.1 从入参直接获取页码跟页大小
|
||||
Integer pageNo = albumIndexQuery.getPageNo();
|
||||
Integer pageSize = albumIndexQuery.getPageSize();
|
||||
//2.2 从ES响应结果获取总记录数
|
||||
long total = searchResponse.hits().total().value();
|
||||
//2.3 计算总页数
|
||||
long totalPages = total % pageSize == 0 ? total / pageSize : total / pageSize + 1;
|
||||
vo.setPageNo(pageNo);
|
||||
vo.setPageSize(pageSize);
|
||||
vo.setTotal(total);
|
||||
vo.setTotalPages(totalPages);
|
||||
|
||||
//3.封装VO中检索到专辑列表集合属性
|
||||
List<Hit<AlbumInfoIndex>> hits = searchResponse.hits().hits();
|
||||
if(CollUtil.isNotEmpty(hits)){
|
||||
//采用Stream流将检索到文档类型从AlbumInfoIndex转为AlbumInfoIndexVo
|
||||
List<AlbumInfoIndexVo> list = hits.stream().map(hit -> {
|
||||
AlbumInfoIndex albumInfoIndex = hit.source();
|
||||
//处理高亮字段
|
||||
Map<String, List<String>> stringListMap = hit.highlight();
|
||||
if (CollUtil.isNotEmpty(stringListMap)) {
|
||||
String hightLightText = stringListMap.get("albumTitle").get(0);
|
||||
albumInfoIndex.setAlbumTitle(hightLightText);
|
||||
}
|
||||
return BeanUtil.copyProperties(albumInfoIndex, AlbumInfoIndexVo.class);
|
||||
}).collect(Collectors.toList());
|
||||
vo.setList(list);
|
||||
}
|
||||
//4.响应VO对象
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue