package com.guwan.backend.service; import cn.easyes.core.conditions.LambdaEsQueryWrapper; import cn.easyes.core.conditions.LambdaEsUpdateWrapper; import com.guwan.backend.pojo.dto.video.VideoDTO; import com.guwan.backend.pojo.entity.Video; import com.guwan.backend.elasticsearch.document.VideoDocument; import com.guwan.backend.elasticsearch.mapper.VideoEsMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import java.util.List; import java.util.stream.Collectors; @Slf4j @Service @ConditionalOnProperty(name = "easy-es.enable", havingValue = "true") @RequiredArgsConstructor public class VideoSearchService { private final VideoEsMapper videoEsMapper; /** * 保存或更新视频文档 */ public void saveOrUpdate(Video video) { VideoDocument document = convertToDocument(video); videoEsMapper.insert(document); } /** * 删除视频文档 */ public void delete(Long id) { videoEsMapper.deleteById(id); } /** * 更新视频观看次数 */ public void updateViewCount(Long id, Integer viewCount) { LambdaEsUpdateWrapper wrapper = new LambdaEsUpdateWrapper<>(); wrapper.eq(VideoDocument::getId, id) .set(VideoDocument::getViewCount, viewCount); videoEsMapper.update(null, wrapper); } /** * 更新视频点赞次数 */ public void updateLikeCount(Long id, Integer likeCount) { LambdaEsUpdateWrapper wrapper = new LambdaEsUpdateWrapper<>(); wrapper.eq(VideoDocument::getId, id) .set(VideoDocument::getLikeCount, likeCount); videoEsMapper.update(null, wrapper); } /** * 搜索视频 */ public List search(String keyword) { // 构建查询条件 LambdaEsQueryWrapper wrapper = new LambdaEsQueryWrapper<>(); wrapper.and(w -> w .match(VideoDocument::getTitle, keyword) .or() .match(VideoDocument::getDescription, keyword) .or() .match(VideoDocument::getTags, keyword) ); // 设置排序 wrapper.orderByDesc(VideoDocument::getScore) .orderByDesc(VideoDocument::getCreatedTime); // 执行查询 List documents = videoEsMapper.selectList(wrapper); // 转换结果 return documents.stream() .map(this::convertToDTO) .collect(Collectors.toList()); } /** * 推荐相似视频 */ public List findSimilar(Long id, int limit) { // 获取当前视频 VideoDocument current = videoEsMapper.selectById(id); if (current == null) { return List.of(); } // 构建查询条件 LambdaEsQueryWrapper wrapper = new LambdaEsQueryWrapper<>(); wrapper.and(w -> w .match(VideoDocument::getTags, current.getTags()) .or() .match(VideoDocument::getTitle, current.getTitle()) .or() .match(VideoDocument::getDescription, current.getDescription()) ); // 排除当前视频 wrapper.ne(VideoDocument::getId, id); // 设置排序和限制 wrapper.orderByDesc(VideoDocument::getScore) .limit(limit); // 执行查询 List documents = videoEsMapper.selectList(wrapper); // 转换结果 return documents.stream() .map(this::convertToDTO) .collect(Collectors.toList()); } private VideoDocument convertToDocument(Video video) { VideoDocument document = new VideoDocument(); BeanUtils.copyProperties(video, document); return document; } private VideoDTO convertToDTO(VideoDocument document) { VideoDTO dto = new VideoDTO(); BeanUtils.copyProperties(document, dto); return dto; } }