Explorar el Código

♻️ refactor(home): 优化推荐和搜索查询构建方式

- 重构job推荐查询,使用更清晰的查询构建器和条件对象
- 优化knowledge查询,将查询构建器改为find方法,简化代码
- 统一搜索功能中的关键词处理,提取为searchKeyword变量
- 使用Brackets重构复杂查询条件,提高可读性和维护性
- 修复personalSkills可能为空的问题,添加filter过滤空值
- 优化用户分类查询,使用更简洁的distinct语法

✨ feat(home): 增强推荐算法精准度

- 改进基于用户技能的职位匹配逻辑,提高推荐相关性
- 优化知识推荐的分类匹配算法,使用更精确的查询条件
- 调整职位推荐排序逻辑,优先展示最新创建的职位

📝 docs(home): 添加代码注释说明

- 为查询构建逻辑添加注释,说明各部分功能
- 标记关键业务逻辑节点,提高代码可维护性
yourname hace 8 meses
padre
commit
c1e68f3762
Se han modificado 1 ficheros con 73 adiciones y 34 borrados
  1. 73 34
      src/server/modules/home/home.service.ts

+ 73 - 34
src/server/modules/home/home.service.ts

@@ -1,4 +1,4 @@
-import { DataSource, Repository } from 'typeorm';
+import { DataSource, Repository, In, Not, Like, MoreThan, Raw, Brackets } from 'typeorm';
 import { PolicyNews } from '../silver-users/policy-news.entity';
 import { Job } from '../silver-jobs/job.entity';
 import { SilverKnowledge } from '../silver-users/silver-knowledge.entity';
@@ -120,24 +120,43 @@ export class HomeService {
     });
     const viewedJobIds = viewedJobs.map(v => v.jobId);
 
-    let query = this.jobRepo
-      .createQueryBuilder('job')
-      .leftJoinAndSelect('job.company', 'company')
-      .where('job.status = :status', { status: 1 });
+    // 构建查询条件
+    const whereConditions: any = {
+      status: 1
+    };
 
     if (viewedJobIds.length > 0) {
-      query = query.andWhere('job.id NOT IN (:...viewedJobIds)', { viewedJobIds });
+      whereConditions.id = Not(In(viewedJobIds));
     }
 
     // 基于用户专业背景匹配
+    const queryBuilder = this.jobRepo
+      .createQueryBuilder('job')
+      .leftJoinAndSelect('job.company', 'company')
+      .where(whereConditions);
+
     if (userProfile?.personalSkills) {
-      const skills = userProfile.personalSkills.split(',').map((s: string) => s.trim());
-      for (let i = 0; i < skills.length; i++) {
-        query = query.orWhere(`job.requirements LIKE :skill${i}`, { [`skill${i}`]: `%${skills[i]}%` });
+      const skills = userProfile.personalSkills.split(',').map((s: string) => s.trim()).filter(s => s);
+      if (skills.length > 0) {
+        const orConditions = skills.map(skill => ({
+          requirements: Like(`%${skill}%`)
+        }));
+        
+        queryBuilder.andWhere(
+          new Brackets(qb => {
+            orConditions.forEach((condition, index) => {
+              if (index === 0) {
+                qb.where(condition);
+              } else {
+                qb.orWhere(condition);
+              }
+            });
+          })
+        );
       }
     }
 
-    return await query
+    return await queryBuilder
       .orderBy('job.createdAt', 'DESC')
       .limit(limit)
       .getMany();
@@ -165,33 +184,38 @@ export class HomeService {
     });
     const viewedKnowledgeIds = userInteractions.map(i => i.knowledgeId);
 
-    // 获取用户浏览过的知识分类,进行相似推荐
-    let categoryQuery = this.knowledgeRepo
+    // 获取用户浏览过的知识分类
+    const userCategories = await this.knowledgeRepo
       .createQueryBuilder('knowledge')
-      .select('DISTINCT knowledge.categoryId', 'categoryId')
-      .where('knowledge.id IN (:...viewedKnowledgeIds)', { viewedKnowledgeIds });
-
-    const userCategories = await categoryQuery.getRawMany();
+      .select('knowledge.categoryId')
+      .distinct(true)
+      .where({ id: In(viewedKnowledgeIds) })
+      .getRawMany();
+    
     const preferredCategories = userCategories.map((c: any) => c.categoryId);
 
-    let query = this.knowledgeRepo
-      .createQueryBuilder('knowledge')
-      .leftJoinAndSelect('knowledge.category', 'category')
-      .where('knowledge.status = :status', { status: 1 });
+    // 构建查询条件
+    const whereConditions: any = {
+      status: 1
+    };
 
     if (viewedKnowledgeIds.length > 0) {
-      query = query.andWhere('knowledge.id NOT IN (:...viewedKnowledgeIds)', { viewedKnowledgeIds });
+      whereConditions.id = Not(In(viewedKnowledgeIds));
     }
 
     if (preferredCategories.length > 0) {
-      query = query.andWhere('knowledge.categoryId IN (:...preferredCategories)', { preferredCategories });
+      whereConditions.categoryId = In(preferredCategories);
     }
 
-    return await query
-      .orderBy('knowledge.viewCount', 'DESC')
-      .addOrderBy('knowledge.createdAt', 'DESC')
-      .limit(limit)
-      .getMany();
+    return await this.knowledgeRepo.find({
+      where: whereConditions,
+      relations: ['category'],
+      order: {
+        viewCount: 'DESC',
+        createdAt: 'DESC'
+      },
+      take: limit
+    });
   }
 
   /**
@@ -256,13 +280,20 @@ export class HomeService {
       companies: []
     };
 
+    const searchKeyword = `%${keyword}%`;
+
     if (type === 'jobs' || type === 'all') {
       results.jobs = await this.jobRepo
         .createQueryBuilder('job')
         .leftJoinAndSelect('job.company', 'company')
         .where('job.status = :status', { status: 1 })
-        .andWhere('(job.title LIKE :keyword OR job.description LIKE :keyword OR company.name LIKE :keyword)')
-        .setParameter('keyword', `%${keyword}%`)
+        .andWhere(
+          new Brackets(qb => {
+            qb.where('job.title LIKE :keyword', { keyword: searchKeyword })
+              .orWhere('job.description LIKE :keyword', { keyword: searchKeyword })
+              .orWhere('company.name LIKE :keyword', { keyword: searchKeyword });
+          })
+        )
         .limit(limit)
         .getMany();
     }
@@ -272,8 +303,12 @@ export class HomeService {
         .createQueryBuilder('knowledge')
         .leftJoinAndSelect('knowledge.category', 'category')
         .where('knowledge.status = :status', { status: 1 })
-        .andWhere('(knowledge.title LIKE :keyword OR knowledge.content LIKE :keyword)')
-        .setParameter('keyword', `%${keyword}%`)
+        .andWhere(
+          new Brackets(qb => {
+            qb.where('knowledge.title LIKE :keyword', { keyword: searchKeyword })
+              .orWhere('knowledge.content LIKE :keyword', { keyword: searchKeyword });
+          })
+        )
         .limit(limit)
         .getMany();
     }
@@ -282,9 +317,13 @@ export class HomeService {
       const Company = this.jobRepo.manager.getRepository('Company');
       results.companies = await Company
         .createQueryBuilder('company')
-        .where('company.status = 1')
-        .andWhere('(company.name LIKE :keyword OR company.description LIKE :keyword)')
-        .setParameter('keyword', `%${keyword}%`)
+        .where('company.status = :status', { status: 1 })
+        .andWhere(
+          new Brackets(qb => {
+            qb.where('company.name LIKE :keyword', { keyword: searchKeyword })
+              .orWhere('company.description LIKE :keyword', { keyword: searchKeyword });
+          })
+        )
         .limit(limit)
         .getMany();
     }