我尝试使用 Neo4j 实施推荐算法,这类似于此page上的实现。
现在我有一个简单的社交示例,其中用户可以:
这个想法是根据其他用户是否是朋友的朋友,玩同一个游戏,住在同一个国家和/或跟踪有问题的用户来制作朋友建议算法。
除了后者之外,使用上面的页面中的示例很容易实现,如下所示:
MATCH (origin)-[r1:FOLLOWS|PLAYS|LIVES_IN]-(c)-[r2:FOLLOWS|PLAYS|LIVES_IN]-(candidate)
WHERE type(r1)=type(r2) AND NOT (source)-[:FOLLOWS]->(candidate)
RETURN candidate, SUM(ROUND(r2.weight) AS boost
ORDER BY boost DESC LIMIT 10
然而,一次完成整个事情的唯一可行方法是与另一个查询联合并处理结果。这些方面的东西:
THE_QUERY_ABOVE
UNION
MATCH (origin)<-[r:FOLLOWS]-(candidate)
RETURN candidate, r.weight as boost
WITH candidate, boost
RETURN DISTINCT candidate, SUM(boost)
ORDER BY boost DESC LIMIT 10
但据我所知,Cypher无法对UNION
结果进行后期处理......
因此,我的问题是:这可以在单个查询中实现吗?以及如何?
如果是,是否有可能的解决方案,我不必在关系中指定权重,以避免在我想改变优先级时改变所有关系?
干杯!
答案 0 :(得分:0)
[EDITED]
OPTIONAL MATCH (origin)-[r1:FOLLOWS|PLAYS|LIVES_IN]-(c)-[r2:FOLLOWS|PLAYS|LIVES_IN]-(candidate)
WHERE type(r1)=type(r2) AND NOT (origin)-[:FOLLOWS]->(candidate)
WITH origin,candidate,(
CASE
WHEN candidate IS NOT NULL THEN [{ candidate: candidate, boost: SUM(ROUND(r2.weight))}]
ELSE NULL END ) AS res1
OPTIONAL MATCH (candidate)-[r3:FOLLOWS]->(origin)
WITH (
CASE
WHEN candidate IS NOT NULL THEN [{ candidate: candidate, boost: SUM(ROUND(r3.weight))}]
ELSE NULL END )+ res1 AS res2
UNWIND res2 AS result
RETURN result.candidate AS candidate, SUM(result.boost) AS boost
ORDER BY boost DESC
LIMIT 10;
这对你有用吗? 如果这不起作用,您可以share a console使用示例数据吗?
它使用共享相同OPTIONAL MATCH
和origin
个节点的2个candidate
子句。每个OPTIONAL MATCH
子句负责处理您的OR
个案例,将该案例的结果放在地图集合中(如果匹配失败,则为NULL
)。接近结束时,集合(包含具有相同结构的映射)被组合并展开为单独的行。最后,具有相同candidate
值的行将boost
值相加,并返回前10个结果(按增加值)。
答案 1 :(得分:0)
您可以使用&#34;可选匹配&#34;