You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改Neo4j Cypher查询计算含平凡路径的对称元路径计数

问题

基于MovieLens100k构建的Neo4j图包含以下元素:

  • 节点:(:User)、(:Movie)、(:Genre)
  • 关系:(:User)-[:RATED]->(:Movie)、(:Movie)-[:HAS_GENRE]->(:Genre)

需要通过元路径 path1=(:User)-[:RATED]->(:Movie)<-[:RATED]-(:User) 计算用户节点间的PathSim相似度。PathSim公式为:

PathSim = 2N₁₂/(N₁₁+N₂₂)

其中N_ij是从用户i到用户j的path1类型路径数。当前查询(1)能计算不同用户间的路径数,但无法统计用户自身的N_ii(即同一用户评分电影形成的“平凡路径”,对应查询(2)的半路径计数)。

现有查询:

查询(1)(计算不同用户间路径数)

MATCH path=(u1:User)-[:RATED]->(:Movie)<-[:RATED]-(u2:User)
WITH u1, u2, COUNT(path) as ct
RETURN u1.id as HeadUser, u2.id as TailUser, CASE WHEN ct is null THEN 0 ELSE ct END AS Overlap

查询(2)(单用户自身半路径计数)

MATCH path=(u1:User {id: 1})-[:RATED]->(:Movie)
WITH COUNT(path) as ct
RETURN CASE WHEN ct is null THEN 0 ELSE ct END AS Overlap

如何修改查询(1)以纳入这些平凡路径?

解决方案

要同时统计不同用户间的路径数和用户自身的N_ii,可以通过整合自身路径统计与跨用户路径统计来实现,以下提供两种可行的修改方案:

方案一:分步统计后合并

// 1. 计算每个用户自身的N_ii(即评分电影的数量,对应自身平凡路径数)
MATCH (u:User)-[:RATED]->(:Movie)
WITH u, COUNT(*) AS self_count
WITH COLLECT({user: u, count: self_count}) AS user_self_data

// 2. 计算不同用户间的路径数
MATCH (u1:User)-[:RATED]->(:Movie)<-[:RATED]-(u2:User)
WHERE u1 <> u2
WITH user_self_data, u1, u2, COUNT(*) AS cross_count

// 3. 合并自身统计与跨用户统计
UNWIND user_self_data AS self_entry
WITH self_entry.user AS u_self, self_entry.count AS self_val,
     COLLECT(CASE WHEN u1 = u_self THEN {target: u2, cnt: cross_count} END) AS cross_out,
     COLLECT(CASE WHEN u2 = u_self THEN {target: u1, cnt: cross_count} END) AS cross_in
UNWIND cross_out + cross_in + [{target: u_self, cnt: self_val}] AS all_records
WITH u_self.id AS HeadUser, all_records.target.id AS TailUser, all_records.cnt AS Overlap
WHERE TailUser IS NOT NULL

RETURN HeadUser, TailUser, Overlap
ORDER BY HeadUser, TailUser

逻辑说明

  • 自身路径数N_ii:每个用户评分的电影数量就是其自身的平凡路径数,每部电影对应一条u->m<-u的路径。
  • 跨用户路径数N_ij(i≠j):保留原查询逻辑,提前排除u1=u2的重复匹配。
  • 合并结果:通过UNWIND将自身统计和双向跨用户统计整合,确保每个用户对(含自身)都有对应的路径数。

方案二:笛卡尔积+可选匹配(更简洁)

// 1. 获取所有用户并计算每个用户的自身路径数
MATCH (u:User)
WITH COLLECT(u) AS all_users

MATCH (u:User)-[:RATED]->(:Movie)
WITH all_users, u, COUNT(*) AS self_count
WITH all_users, MAP {u.id: self_count} AS self_count_map

// 2. 生成所有用户对(含自身),匹配跨用户路径并合并统计
UNWIND all_users AS u1
UNWIND all_users AS u2
OPTIONAL MATCH (u1)-[:RATED]->(m:Movie)<-[:RATED]-(u2)
WITH u1.id AS HeadUser, u2.id AS TailUser,
     COUNT(m) AS cross_count,
     self_count_map[u1.id] AS self_val

// 3. 区分自身与跨用户场景,返回结果
RETURN HeadUser, TailUser,
       CASE WHEN HeadUser = TailUser THEN self_val ELSE cross_count END AS Overlap
ORDER BY HeadUser, TailUser

逻辑说明

  • 先获取所有用户集合,计算每个用户的自身路径数并存入Map方便调用。
  • 通过笛卡尔积生成所有可能的用户对(包括u1=u2的情况)。
  • 对每个用户对,用OPTIONAL MATCH匹配跨用户路径,当用户是自身时直接取预计算的自身路径数,否则取跨用户路径计数。

两种方案都能一次性得到包含所有用户对(含自身)的N_ij值,可直接用于后续PathSim相似度计算。

内容的提问来源于stack exchange,提问作者Emanuele Maduli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 19:22:41