yulongyan_citu 1 سال پیش
والد
کامیت
0bf736cca3
4فایلهای تغییر یافته به همراه123 افزوده شده و 44 حذف شده
  1. 2 2
      Dockerfile
  2. 0 2
      README.md
  3. 99 20
      functions/similarity_judge.py
  4. 22 20
      interfaces/rocketmq.py

+ 2 - 2
Dockerfile

@@ -5,13 +5,13 @@ FROM python:3.7-slim
 WORKDIR /usr/src/app
 
 # 将项目的依赖文件复制到工作目录
-COPY requirements.txt ./
+COPY /opt/mendunr_project/requirements.txt ./
 
 # 安装依赖
 RUN pip install --no-cache-dir -r requirements.txt
 
 # 将Python脚本复制到容器中
-COPY . .
+COPY /opt/mendunr_project ./
 
 # 暴露应用的端口
 EXPOSE 3333

+ 0 - 2
README.md

@@ -1,2 +0,0 @@
-# mendunr_project
-

+ 99 - 20
functions/similarity_judge.py

@@ -73,22 +73,20 @@ def similar_job(uniqueid,start,end):
             WITH node2.uniqueId AS job_id, node2.name AS job_name, similarity
             ORDER BY similarity DESC
             // 返回最相似的 job 节点
-            with count(job_id) as total,collect(job_id) as job_ids
-            return total,job_ids[{start}..{end}] as jobIds
+            //with count(job_id) as total,collect(job_id) as job_ids
+            with collect(job_id) as job_ids
+            return job_ids[{start}..{end}] as jobIds
             """
-            result = connect_graph.run(query, Id=uniqueid).data()
+            result = connect_graph.run(query, Id=uniqueid).evaluate()
             if result:
-                total = result[0]['total']
-                jobIds = result[0]['jobIds']
-                return jobIds, total
+                return result
             else:
-                total = 10
-                return default_job(), total
+                return default_job()
         else:
-            return default_job(),10
+            return default_job()
     except Exception as e:
         current_app.logger.error(f'similar_job error: {e}')
-        return default_job(),10
+        return default_job()
 
 
 # 职位详情推荐类似的职位
@@ -119,22 +117,20 @@ def home_job(uniqueid,start,end):
             MATCH (j:job)-[:connection]->(jl)
             // 7. 返回 job 的 id 和总数
             WITH s, j.uniqueId AS jobId
-            WITH count(DISTINCT jobId) AS total, collect(DISTINCT jobId) AS jobIds
-            RETURN total, jobIds[{start}..{end}] AS jobIds
+            //WITH count(DISTINCT jobId) AS total, collect(DISTINCT jobId) AS jobIds
+            with collect(DISTINCT jobId) AS jobIds
+            RETURN jobIds[{start}..{end}] AS jobIds
             """
-            result = connect_graph.run(query,Id = uniqueid).data()
+            result = connect_graph.run(query,Id = uniqueid).evaluate()
             if result:
-                total = result[0]['total']
-                jobIds = result[0]['jobIds']
-                return jobIds, total
+                return result
             else:
-                total = 10
-                return default_job(),total
+                return default_job()
         else:
-            return default_job(),10
+            return default_job()
     except Exception as e:
         current_app.logger.error(f'home_job error: {e}')
-        return default_job(),10
+        return default_job()
 
 
 def default_job():
@@ -150,4 +146,87 @@ def default_job():
         return result
     except Exception as e:
         current_app.logger.error(f'default_job error: {e}')
+        return []
+
+def draw_person_graph():
+    try:
+        # 先判断图谱中是否存在投影图,不存在直接drop会报错
+        create_query = """CALL gds.graph.exists('personGraph') YIELD exists
+                                 RETURN CASE exists WHEN true THEN 1 ELSE 0 END as graphExists"""
+        result = connect_graph.run(create_query).evaluate()
+        if result == 0:
+            create_query = """
+                   // 创建图投影
+                   CALL gds.graph.project(
+                       'personGraph',
+                       ['seeker', 'seekerLabel'],
+                       {
+                           r: {
+                               type: 'connection',
+                               orientation: 'UNDIRECTED'
+                           }
+                       }
+                   )
+                   """
+            connect_graph.run(create_query)
+    except Exception as e:
+        current_app.logger.error(f'draw_graph error: {e}')
+        return str(e)
+
+
+def home_person(uniqueid,start,end):
+    try:
+        if uniqueid:
+            query = f""" 
+            // 1. 查找 job 节点
+            MATCH (j:job {{uniqueId: $Id}})
+            // 2. 获取 jobLabel 节点
+            WITH j
+            MATCH (j)-[:connection]->(jl:jobLabel)
+            // 3. 获取 seekerLabel 节点
+            WITH j, jl
+            MATCH (sl:seekerLabel)
+            // 4. 计算jobLabel 和 seekerLabel 之间的 Levenshtein 距离
+            WITH j, jl, sl, apoc.text.levenshteinDistance( jl.name,sl.name) AS distance
+            // 5. 找到距离最小的 seekerLabel
+            WITH j, jl, sl, distance
+            ORDER BY distance ASC
+            WITH j, jl, collect({{sl: sl, distance: distance}}) AS seekerLabels
+            WITH j, jl,seekerLabels, min(seekerLabels[0].distance) AS min_distance
+            UNWIND seekerLabels AS sl_with_distance
+            WITH j, jl, sl_with_distance.sl AS sl, sl_with_distance.distance AS distance, min_distance
+            WHERE distance <= min_distance
+            // 6. 获取 seeker 节点
+            WITH j, jl, sl
+            MATCH (s:seeker)-[:connection]->(sl)
+            // 7. 返回 seeker 的 id 和总数
+            WITH j, s.uniqueId AS seekerId
+            //WITH count(DISTINCT seekerId) AS total, collect(DISTINCT seekerId) AS seekerIds
+            with collect(DISTINCT seekerId) AS seekerIds
+            RETURN seekerIds[{start}..{end}] AS seekerIds
+            """
+            result = connect_graph.run(query,Id = uniqueid).evaluate()
+            if result:
+                return result
+            else:
+                return default_person()
+        else:
+            return default_person()
+    except Exception as e:
+        current_app.logger.error(f'home_job error: {e}')
+        return default_person()
+
+def default_person():
+    try:
+        query = """
+        MATCH (n:seeker)-[r:connection]-(m:seekerLabel)
+        WITH n, COUNT(m) AS num_connections
+        ORDER BY num_connections DESC
+        LIMIT 10
+        RETURN collect(n.uniqueId) AS seeker_ids
+        """
+        result = connect_graph.run(query).evaluate()
+        return result
+    except Exception as e:
+        current_app.logger.error(f'default_person error: {e}')
         return []

+ 22 - 20
interfaces/rocketmq.py

@@ -3,7 +3,7 @@ from configs.result import success
 from functions.label_number import job_label, enterprise_label, seeker_label
 from functions.operate_graph import operate_job, operate_enterprise, operate_seeker
 import logging
-from functions.similarity_judge import similar_job, similar_seeker, draw_graph, home_job
+from functions.similarity_judge import similar_job, similar_seeker, draw_graph, home_job, home_person
 from functions.solve_graph import llm_client
 logger = logging.getLogger(__name__)
 rocket = Blueprint('rocket', __name__)
@@ -88,19 +88,17 @@ def match_job():
         start = (page - 1) * page_size
         end = page * page_size
         if type == 'job':
-            id_list,total = similar_job(uniqueid,start,end)
+            id_list = similar_job(uniqueid,start,end)
         else:
             current_app.logger.error('match_job Invalid type')
-            id_list,total = [],0
+            id_list = []
 
         return jsonify(success(id_list, "success"))
-
-
     except Exception as e:
         current_app.logger.error(f'match_job error: {e}')
         return jsonify(success([], "success"))
 
-# 首页未登录、人登录之后推荐的职位
+# 人登录之后推荐的职位
 @rocket.route('/recommend/job',methods=['POST'])
 def recommend_job():
     try:
@@ -115,35 +113,39 @@ def recommend_job():
 
         draw_graph()
         if type == 'job':
-            id_list,total = home_job(uniqueid,start,end)
+            id_list = home_job(uniqueid,start,end)
         else:
             current_app.logger.error('match_job Invalid type')
-            id_list,total = [],0
+            id_list = []
         return jsonify(success(id_list, "success"))
 
     except Exception as e:
         current_app.logger.error(f'recommend_job error: {e}')
         return jsonify(success([], "success"))
 
-
-# 找职位:通过标签找职位,推荐职位
-@rocket.route('/search/job',methods=['POST'])
-def search_job():
+# 人登录之后推荐的职位
+@rocket.route('/recommend/person',methods=['POST'])
+def recommend_person():
     try:
         receiver = request.get_json()
-        uniqueid = receiver.get('id', [])  #职位对应的id
-        description = receiver.get('content', '')  # 一段描述内容
-        type = receiver.get('type', '')  # 1.找人  job
-        draw_graph()
-        if type == 'job':
-            id_list = similar_job(uniqueid,description)
+        page = int(receiver.get('current', 1))
+        page_size = int(receiver.get('size', 10))
+        uniqueid = receiver.get('id', "")  # 职位对应的id
+        type = receiver.get('type', '')  # 推荐对应的person
+        # 起止范围
+        start = (page-1) * page_size
+        end = page * page_size
+
+        draw_person_graph()
+        if type == 'person':
+            id_list = home_person(uniqueid,start,end)
         else:
-            current_app.logger.error('query_graph Invalid type')
+            current_app.logger.error('match_job Invalid type')
             id_list = []
         return jsonify(success(id_list, "success"))
 
     except Exception as e:
-        current_app.logger.error(f'match_job error: {e}')
+        current_app.logger.error(f'recommend_job error: {e}')
         return jsonify(success([], "success"))