浏览代码

匹配度算法修改

lrf 7 月之前
父节点
当前提交
1a168cd838
共有 3 个文件被更改,包括 163 次插入39 次删除
  1. 10 5
      src/controller/contactSearch.controller.ts
  2. 86 34
      src/service/accurateMatching.service.ts
  3. 67 0
      src/service/contactSearch.service.ts

+ 10 - 5
src/controller/contactSearch.controller.ts

@@ -18,9 +18,11 @@ export class ContactSearchController {
   async demand(@Query('keyword') keyword: string, @Query('id') id: number) {
   async demand(@Query('keyword') keyword: string, @Query('id') id: number) {
     if (!keyword) return;
     if (!keyword) return;
     const supplyConfig = { index: 'supply', fields: ['name', 'tags', 'brief'] };
     const supplyConfig = { index: 'supply', fields: ['name', 'tags', 'brief'] };
-    const sres = await this.csService.search(keyword, supplyConfig, 'demand', id);
+    // const sres = await this.csService.search(keyword, supplyConfig, 'demand', id);
+    const sres = await this.csService.newSearch(keyword, supplyConfig, 'demand', id);
     const achievementConfig = { index: 'achievement', fields: ['name', 'tags', 'brief'] };
     const achievementConfig = { index: 'achievement', fields: ['name', 'tags', 'brief'] };
-    const ares = await this.csService.search(keyword, achievementConfig, 'demand', id);
+    // const ares = await this.csService.search(keyword, achievementConfig, 'demand', id);
+    const ares = await this.csService.newSearch(keyword, achievementConfig, 'demand', id);
     return sres || ares;
     return sres || ares;
   }
   }
 
 
@@ -32,7 +34,8 @@ export class ContactSearchController {
   @Get('/supply')
   @Get('/supply')
   async supply(@Query('keyword') keyword: string, @Query('id') id: number) {
   async supply(@Query('keyword') keyword: string, @Query('id') id: number) {
     const config = { index: 'demand', fields: ['name', 'tags', 'brief'] };
     const config = { index: 'demand', fields: ['name', 'tags', 'brief'] };
-    const res = await this.csService.search(keyword, config, 'supply', id);
+    // const res = await this.csService.search(keyword, config, 'supply', id);
+    const res = await this.csService.newSearch(keyword, config, 'supply', id);
     return res;
     return res;
   }
   }
 
 
@@ -44,7 +47,8 @@ export class ContactSearchController {
   @Get('/project')
   @Get('/project')
   async projectr(@Query('keyword') keyword: string, @Query('id') id: number) {
   async projectr(@Query('keyword') keyword: string, @Query('id') id: number) {
     const config = { index: 'demand', fields: ['name', 'tags', 'brief'] };
     const config = { index: 'demand', fields: ['name', 'tags', 'brief'] };
-    const res = await this.csService.search(keyword, config, 'project', id);
+    // const res = await this.csService.search(keyword, config, 'project', id);
+    const res = await this.csService.newSearch(keyword, config, 'project', id);
     return res;
     return res;
   }
   }
 
 
@@ -56,7 +60,8 @@ export class ContactSearchController {
   @Get('/achievement')
   @Get('/achievement')
   async achievement(@Query('keyword') keyword: string, @Query('id') id: number) {
   async achievement(@Query('keyword') keyword: string, @Query('id') id: number) {
     const config = { index: 'demand', fields: ['name', 'tags', 'brief'] };
     const config = { index: 'demand', fields: ['name', 'tags', 'brief'] };
-    const res = await this.csService.search(keyword, config, 'achievement', id);
+    // const res = await this.csService.search(keyword, config, 'achievement', id);
+    const res = await this.csService.newSearch(keyword, config, 'achievement', id);
     return res;
     return res;
   }
   }
 }
 }

+ 86 - 34
src/service/accurateMatching.service.ts

@@ -31,18 +31,18 @@ export class AccurateMatchingService {
     const config = { index: 'achievement', fields: ['name', 'tags', 'area', 'brief'] };
     const config = { index: 'achievement', fields: ['name', 'tags', 'area', 'brief'] };
     return this.search(keyword, config, skip, limit);
     return this.search(keyword, config, skip, limit);
   }
   }
-
+  //由供给信息查询
   async forDemandSearch(keyword: string, skip = 0, limit = 10, id) {
   async forDemandSearch(keyword: string, skip = 0, limit = 10, id) {
     const fields = ['name', 'tags', 'brief'];
     const fields = ['name', 'tags', 'brief'];
-    const config = { index: ['supply', 'achievement'], fields };
-    const origin_index = 'demand';
+    const config = { index: ['demand', 'achievement'], fields };
+    const origin_index = 'supply';
     return await this.manyIndexsSearch(keyword, config, skip, limit, origin_index, id);
     return await this.manyIndexsSearch(keyword, config, skip, limit, origin_index, id);
   }
   }
-
+  // 由需求信息查询
   async forSupplySearch(keyword: string, skip = 0, limit = 10, id) {
   async forSupplySearch(keyword: string, skip = 0, limit = 10, id) {
     const fields = ['name', 'tags', 'brief'];
     const fields = ['name', 'tags', 'brief'];
-    const config = { index: ['demand', 'achievement'], fields };
-    const origin_index = 'supply';
+    const config = { index: ['supply', 'achievement'], fields };
+    const origin_index = 'demand';
     return await this.manyIndexsSearch(keyword, config, skip, limit, origin_index, id);
     return await this.manyIndexsSearch(keyword, config, skip, limit, origin_index, id);
   }
   }
 
 
@@ -73,26 +73,41 @@ export class AccurateMatchingService {
 
 
   async manyIndexsSearch(keyword: string, config: object, skip: number, limit: number, origin_index: string, id?: number) {
   async manyIndexsSearch(keyword: string, config: object, skip: number, limit: number, origin_index: string, id?: number) {
     const index = get(config, 'index');
     const index = get(config, 'index');
-    const fields = get(config, 'fields', []);
+    // const fields = get(config, 'fields', []);
     const user_id = get(this.ctx, 'user.id');
     const user_id = get(this.ctx, 'user.id');
-    const must: any = [
+    // const must: any = [
+    //   {
+    //     match: {
+    //       name: {
+    //         query: keyword,
+    //       },
+    //     },
+    //   },
+    // ];
+    const must_not = [
       {
       {
-        multi_match: {
-          query: keyword,
-          fields,
-          type: 'best_fields',
-          tie_breaker: 0.5,
+        match: {
+          user: user_id,
         },
         },
       },
       },
     ];
     ];
-    const must_not = [
+    const should: any = [
       {
       {
-        match: {
-          user: user_id,
+        constant_score: {
+          filter: {
+            bool: {
+              must: {
+                match: { name: keyword },
+              },
+            },
+          },
+          boost: 3,
         },
         },
       },
       },
     ];
     ];
-    const filter = [];
+    const queries = [];
+    queries.push({ bool: { must_not, should: { match: { name: keyword } } } });
+    let fieldValue, industryValue;
     if (id) {
     if (id) {
       const res = await this.esClient.search({
       const res = await this.esClient.search({
         index: origin_index,
         index: origin_index,
@@ -100,33 +115,70 @@ export class AccurateMatchingService {
       });
       });
       const originResult = this.dealResponses(res);
       const originResult = this.dealResponses(res);
       const industry = get(head(get(originResult, 'data')), 'industry');
       const industry = get(head(get(originResult, 'data')), 'industry');
+      // 产业
       if (industry && industry !== '') {
       if (industry && industry !== '') {
-        filter.push({ term: { industry } });
+        industryValue = industry;
+        should.push({
+          constant_score: {
+            filter: {
+              bool: {
+                must: {
+                  term: { industry },
+                },
+              },
+            },
+            boost: 1,
+          },
+        });
       }
       }
+      // 技术领域
+      const field = get(head(get(originResult, 'data')), 'field');
+      if (field && field !== '') {
+        fieldValue = field;
+        should.push({
+          constant_score: {
+            filter: {
+              bool: {
+                must: {
+                  match: { field },
+                },
+              },
+            },
+            boost: 1,
+          },
+        });
+      }
+    }
+
+    if (fieldValue) {
+      queries.push({ match: { field: fieldValue } });
+    }
+    if (industryValue) {
+      queries.push({ term: { industry: industryValue } });
     }
     }
+
     const result = await this.esClient.search({
     const result = await this.esClient.search({
       index,
       index,
+      // constant_score方式
+      // query: {
+      //   bool: {
+      //     must_not,
+      //     should,
+      //     minimum_should_match: 1,
+      //   },
+      // },
+      // dis_max方式
       query: {
       query: {
-        bool: {
-          must,
-          must_not,
-          filter,
+        dis_max: {
+          queries,
+          tie_breaker: 0.3,
+          boost: 0.7,
         },
         },
       },
       },
-      // highlight: {
-      //   fields: {
-      //     name: {
-      //       pre_tags: ['<em>'],
-      //       post_tags: ['</em>'],
-      //     },
-      //     brief: {
-      //       pre_tags: ['<em>'],
-      //       post_tags: ['</em>'],
-      //     },
-      //   },
-      // },
+      // min_score: 3,
       size: limit,
       size: limit,
       from: skip,
       from: skip,
+      explain: true,
     });
     });
     const returnData = this.dealResponses(result);
     const returnData = this.dealResponses(result);
     return returnData;
     return returnData;

+ 67 - 0
src/service/contactSearch.service.ts

@@ -16,6 +16,73 @@ export class ContactSearchService {
     const esClient = new Client(this.esConfig);
     const esClient = new Client(this.esConfig);
     this.esClient = esClient;
     this.esClient = esClient;
   }
   }
+
+  async newSearch(keyword: string, config: object, form: string, id: number) {
+    const index = get(config, 'index');
+    // const fields = get(config, 'fields', []);
+    const user_id = get(this.ctx, 'user.id');
+    const queries = [];
+    // match_phrase
+    queries.push({
+      bool: {
+        should: [{ match: { name: keyword } }],
+        must: [{ term: { status: '1' } }, { term: { user: user_id } }],
+        minimum_should_match: 1,
+      },
+    });
+    // 找到这条数据
+    const sourceResult = await this.esClient.search({
+      index: form,
+      query: { bool: { must: { match: { id } } } },
+    });
+    const sourceData = this.dealResponses(sourceResult);
+    const industry = get(head(get(sourceData, 'data')), 'industry');
+    const field = get(head(get(sourceData, 'data')), 'field');
+    // if (field && field !== '') queries.push({ match: { field } });
+    // if (industry && industry !== '') queries.push({ term: { industry } });
+    if (field && field !== '')
+      queries.push({
+        bool: {
+          should: [{ match: { field } }],
+          must: [{ term: { status: '1' } }, { term: { user: user_id } }],
+          minimum_should_match: 1,
+        },
+      });
+    if (industry && industry !== '')
+      queries.push({
+        bool: {
+          should: [{ term: { industry } }],
+          must: [{ term: { status: '1' } }, { term: { user: user_id } }],
+          minimum_should_match: 1,
+        },
+      });
+    // 因为新加条件了:status和user,所以关系系数增加了一倍
+    const result = await this.esClient.search({
+      index,
+      query: {
+        dis_max: {
+          queries,
+          tie_breaker: 0.6,
+          boost: 0.7,
+        },
+      },
+      explain: true,
+    });
+    const returnData = this.dealResponses(result);
+    const list = get(returnData, 'data', []); //最符合正向匹配的前10个数据
+    // 查找,是否有推荐度为4或4以上的数据.
+    const data = head(list);
+    if (!data) return false;
+    else {
+      // 先看下正向匹配(由 浏览数据的 标题 作为关键词, 到用户审核过的数据中进行查询)
+      const recommend = get(data, '_recommend', 0);
+      const firRecommend = recommend >= 3;
+      // 如果大于等于4,则返回成功
+      if (firRecommend) return true;
+    }
+    return false;
+  }
+
   /**
   /**
    * 联系申请相似度查询
    * 联系申请相似度查询
    * 正反两次验证:
    * 正反两次验证: