forked from Gitlink/microservices
feat(全局搜索): 实现超算专区全局搜索功能
1. 搜索专区项目时返回项目的语言、项目类别、最佳更新时间 2. 搜索专区资源时返回资源的附件数量、下载次数、发布时间 3. 搜索专区新闻时返回新闻的阅读数、发布时间 4. 搜索专区会员时返回会员的会员名称、会员分类名称、会员头像
This commit is contained in:
parent
a0384614d3
commit
fded90d57c
|
|
@ -163,6 +163,7 @@ public class GlobalSearchServiceImpl implements IGlobalSearchService {
|
|||
|
||||
JSONObject extendData = new JSONObject();
|
||||
extendData.put("visits", doc.getVisits());
|
||||
extendData.put("publishTime", doc.getPublishTime());
|
||||
result.setExtendData(extendData);
|
||||
results.add(result);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,4 +19,6 @@ public class ZoneMemberWithScore extends ZoneMember implements Serializable {
|
|||
* 全文搜索相关度评分(来自 MySQL MATCH...AGAINST)
|
||||
*/
|
||||
private Double searchScore;
|
||||
|
||||
private String memberTypeName;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
package com.microservices.zone.project.domain;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.microservices.zone.project.domain.ZoneProject;
|
||||
import com.microservices.zone.project.domain.vo.ZoneProjectDataVo;
|
||||
import com.microservices.zone.search.dto.GlobalSearchResult;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
|
|
@ -19,4 +22,27 @@ public class ZoneProjectWithScore extends ZoneProject implements Serializable {
|
|||
* 全文搜索相关度评分(来自 MySQL MATCH...AGAINST)
|
||||
*/
|
||||
private Double searchScore;
|
||||
|
||||
public GlobalSearchResult toGlobalSearchResult(ZoneProjectDataVo zoneProjectDataVo) {
|
||||
GlobalSearchResult result = new GlobalSearchResult();
|
||||
result.setType("zone_project");
|
||||
result.setId(this.getId());
|
||||
result.setTitle(this.getName());
|
||||
result.setContent(this.getFullName());
|
||||
result.setDeptId(this.getDeptId());
|
||||
result.setZoneId(this.getZoneId());
|
||||
result.setCreateTime(this.getCreateTime());
|
||||
|
||||
if (zoneProjectDataVo != null) {
|
||||
result.setExtendData(zoneProjectDataVo.getProjectProperties());
|
||||
}
|
||||
|
||||
// 使用数据库返回的实际搜索评分
|
||||
Double score = this.getSearchScore();
|
||||
if (score == null || score == 0.0) {
|
||||
score = 0.1; // LIKE 匹配的最小评分
|
||||
}
|
||||
result.setScore(score);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.microservices.zone.project.service;
|
|||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.microservices.common.core.web.page.GenericsTableDataInfo;
|
||||
import com.microservices.zone.project.domain.ZoneProject;
|
||||
import com.microservices.zone.project.domain.vo.*;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -147,4 +148,5 @@ public interface IZoneProjectService {
|
|||
int auditZoneProject(ZoneProjectAuditVo zoneProjectAuditVo);
|
||||
|
||||
GenericsTableDataInfo<JSONObject> selectMyGitlinkProjectListByZone(Long zoneId, MyGitLinkProjectSearchVo myGitLinkProjectSearchVo);
|
||||
List<ZoneProjectDataVo> toZoneProjectDataVoList(List<ZoneProject> zoneProjectList);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,7 +125,8 @@ public class ZoneProjectServiceImpl implements IZoneProjectService {
|
|||
return PageUtils.toListPage(zoneProjectList, this::toZoneProjectDataVoList);
|
||||
}
|
||||
|
||||
private List<ZoneProjectDataVo> toZoneProjectDataVoList(List<ZoneProject> zoneProjectList) {
|
||||
@Override
|
||||
public List<ZoneProjectDataVo> toZoneProjectDataVoList(List<ZoneProject> zoneProjectList) {
|
||||
List<ZoneProjectDataVo> zoneProjectDataVoList = new ArrayList<>();
|
||||
// 原方案为遍历项目聚合再逐一从GitLink获取对应项目详情,此方案延时过高,调整为根据项目Id批量获取GitLink项目信息
|
||||
List<String> gitLinkProjectIdList = zoneProjectList
|
||||
|
|
|
|||
|
|
@ -19,4 +19,6 @@ public class ZoneResourceWithScore extends ZoneResource implements Serializable
|
|||
* 全文搜索相关度评分(来自 MySQL MATCH...AGAINST)
|
||||
*/
|
||||
private Double searchScore;
|
||||
|
||||
private Long downloadCount;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@ import com.microservices.system.api.domain.SysFileInfo;
|
|||
import com.microservices.system.api.model.LoginUser;
|
||||
import com.microservices.zone.project.domain.ZoneProject;
|
||||
import com.microservices.zone.project.domain.ZoneProjectWithScore;
|
||||
import com.microservices.zone.project.domain.vo.ZoneProjectDataVo;
|
||||
import com.microservices.zone.project.mapper.ZoneProjectMapper;
|
||||
import com.microservices.zone.project.service.IZoneProjectService;
|
||||
import com.microservices.zone.resource.domain.ZoneResource;
|
||||
import com.microservices.zone.resource.domain.ZoneResourceWithScore;
|
||||
import com.microservices.zone.resource.mapper.ZoneResourceMapper;
|
||||
|
|
@ -57,6 +59,9 @@ public class GlobalSearchServiceImpl implements IGlobalSearchService {
|
|||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
@Autowired
|
||||
private IZoneProjectService projectService;
|
||||
|
||||
private static final String SEARCH_CACHE_PREFIX = "search:cache:";
|
||||
private static final long CACHE_EXPIRE_SECONDS = 300; // 5分钟
|
||||
|
||||
|
|
@ -185,23 +190,12 @@ public class GlobalSearchServiceImpl implements IGlobalSearchService {
|
|||
(request.getPageNum() - 1) * request.getPageSize(),
|
||||
request.getPageSize()
|
||||
);
|
||||
List<ZoneProject> zoneProjectList = projects.stream().map(x -> (ZoneProject) x).collect(Collectors.toList());
|
||||
List<ZoneProjectDataVo> projectDataVoList = projectService.toZoneProjectDataVoList(zoneProjectList);
|
||||
|
||||
for (ZoneProjectWithScore project : projects) {
|
||||
GlobalSearchResult result = new GlobalSearchResult();
|
||||
result.setType("zone_project");
|
||||
result.setId(project.getId());
|
||||
result.setTitle(project.getName());
|
||||
result.setContent(project.getFullName());
|
||||
result.setDeptId(project.getDeptId());
|
||||
result.setZoneId(project.getZoneId());
|
||||
result.setCreateTime(project.getCreateTime());
|
||||
|
||||
// 使用数据库返回的实际搜索评分
|
||||
Double score = project.getSearchScore();
|
||||
if (score == null || score == 0.0) {
|
||||
score = 0.1; // LIKE 匹配的最小评分
|
||||
}
|
||||
result.setScore(score);
|
||||
ZoneProjectDataVo zoneProjectDataVo = projectDataVoList.stream().filter(x -> x.getId().equals(project.getId())).findFirst().orElse(null);
|
||||
GlobalSearchResult result = project.toGlobalSearchResult(zoneProjectDataVo);
|
||||
results.add(result);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
|
@ -243,6 +237,14 @@ public class GlobalSearchServiceImpl implements IGlobalSearchService {
|
|||
// 查询并过滤匹配的附件
|
||||
if (StringUtils.isNotEmpty(resource.getFileIds())) {
|
||||
try {
|
||||
JSONObject extendData = new JSONObject();
|
||||
extendData.put("downloadCount", resource.getDownloadCount());
|
||||
if (resource.getFileIds() != null) {
|
||||
String[] fileIds = resource.getFileIds().split(",");
|
||||
extendData.put("fileCount", fileIds.length);
|
||||
}
|
||||
|
||||
|
||||
R<List<SysFileInfo>> fileResponse = remoteFileService.getFileList(resource.getFileIds());
|
||||
if (fileResponse != null && fileResponse.getCode() == 200 && fileResponse.getData() != null) {
|
||||
List<JSONObject> matchedFiles = fileResponse.getData().stream()
|
||||
|
|
@ -258,11 +260,12 @@ public class GlobalSearchServiceImpl implements IGlobalSearchService {
|
|||
.collect(Collectors.toList());
|
||||
|
||||
if (!matchedFiles.isEmpty()) {
|
||||
JSONObject extendData = new JSONObject();
|
||||
|
||||
extendData.put("matchedFiles", matchedFiles);
|
||||
result.setExtendData(extendData);
|
||||
|
||||
}
|
||||
}
|
||||
result.setExtendData(extendData);
|
||||
} catch (Exception e) {
|
||||
logger.warn("查询附件信息失败: resourceId={}, error={}", resource.getId(), e.getMessage());
|
||||
}
|
||||
|
|
@ -326,12 +329,10 @@ public class GlobalSearchServiceImpl implements IGlobalSearchService {
|
|||
if (StringUtils.isNotEmpty(member.getImageUrl())) {
|
||||
extendData.put("imageUrl", member.getImageUrl());
|
||||
}
|
||||
if (member.getMemberLevelId() != null) {
|
||||
extendData.put("memberLevelId", member.getMemberLevelId());
|
||||
}
|
||||
if (member.getSysUser() != null && StringUtils.isNotEmpty(member.getSysUser().getAvatar())) {
|
||||
extendData.put("userAvatar", member.getSysUser().getAvatar());
|
||||
if (StringUtils.isNotEmpty(member.getMemberTypeName())) {
|
||||
extendData.put("memberTypeName", member.getMemberTypeName());
|
||||
}
|
||||
|
||||
result.setExtendData(extendData);
|
||||
} catch (Exception e) {
|
||||
logger.warn("构建会员扩展数据失败: memberId={}, error={}", member.getId(), e.getMessage());
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@
|
|||
<resultMap type="com.microservices.zone.member.domain.ZoneMemberWithScore"
|
||||
id="ZoneMemberWithScoreResult" extends="ZoneMemberResult">
|
||||
<result property="searchScore" column="search_score"/>
|
||||
<result property="memberTypeName" column="typeName"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectZoneMemberAliasVo">
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
<resultMap type="com.microservices.zone.resource.domain.ZoneResourceWithScore"
|
||||
id="ZoneResourceWithScoreResult" extends="ZoneResourceResult">
|
||||
<result property="searchScore" column="search_score"/>
|
||||
<result property="downloadCount" column="download_count"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectZoneResourceVo">
|
||||
|
|
@ -361,6 +362,7 @@
|
|||
zr.create_by, zr.create_time, zr.update_by, zr.update_time,
|
||||
zr.editor_type, zr.audit_status, zr.audit_time, zr.audit_by,
|
||||
zr.summary, zr.remark, zr.keywords, zr.extend_data,
|
||||
(select sum(download_count) from sys_file_info sf where FIND_IN_SET(sf.file_id,zr.file_ids)) as download_count,
|
||||
MATCH(zr.name, zr.keywords) AGAINST(#{keyword} IN NATURAL LANGUAGE MODE) AS search_score
|
||||
FROM zone_resource zr
|
||||
WHERE zr.zone_id = #{zoneId}
|
||||
|
|
|
|||
Loading…
Reference in New Issue