Neo4j - 遍历查找还不是用户朋友的朋友的朋友

问题描述 投票:0回答:1

使用 Neo4j 2.0.1,我试图在任何级别(2-5)的深度上找到与用户不是朋友的朋友的朋友。

起初,我使用 cypher 来获取朋友的所有朋友,但遗憾的是,当我尝试在深度 4 和 5 查找朋友的朋友时,性能非常糟糕。因此,我从 cypher 转向遍历 Rest api,稍后我将使用Neo4jPHP中的遍历。这就是我所做的改变:

注:

- there are 10 users with 5 friends of each user
- user that I want to traverse at depth of 3 is 1
- traversal at depth of 3

好友列表:

User | Friends
 1   | 9,2,8,7,5
 2   | 1,6,3,8,10
 3   | 5,7,1,10,2
 4   | 3,10,6,9,5
 5   | 4,8,1,9,3
 6   | 7,9,3,2,10
 7   | 9,5,10,6,8
 8   | 6,9,1,10,5
 9   | 6,5,10,1,8
 10  | 8,6,4,5,9

密码:

MATCH (U:User)-[F:Friend]->(FU:User)-[FF:Friend]->(FFU:User)
WHERE U.user_id=1
WITH DISTINCT U, FFU
WHERE FFU<>U 
WITH DISTINCT U, FFU
MATCH (FFU:User)-[FFF:Friend]->(FFFU:User)
WHERE FFFU<>U AND NOT (U)-[:Friend]->(FFFU)
RETURN DISTINCT FFFU.username;

Travesal Rest Api[更新]:

POST http://localhost:7474/db/data/node/1/traverse/node
{
  "order" : "breadth_first",
  "uniqueness" : "node_global",
  "prune_evaluator" : {
    "name" : "none",
    "language" : "builtin"
  },
  "return_filter" : {
    "body" : "position.endNode().getProperty('user_id')!=1 && position.endNode().getProperty('user_id')!=9 && position.endNode().getProperty('user_id')!=2 && position.endNode().getProperty('user_id')!=8 && position.endNode().getProperty('user_id')!=7 && position.endNode().getProperty('user_id')!=5;",
    "language" : "javascript"
  },
  "relationships" : {
    "direction" : "out",
    "type" : "Friend"
  },
  "max_depth" : 3
}

Neo4jPHP 遍历[更新]:

$traversal->addRelationship('Friend', Relationship::DirectionOut)
    ->setPruneEvaluator(Traversal::PruneNone)
    ->setReturnFilter('javascript', "position.endNode().getProperty('user_id')!=1 && position.endNode().getProperty('user_id')!=9 && position.endNode().getProperty('user_id')!=2 && position.endNode().getProperty('user_id')!=8 && position.endNode().getProperty('user_id')!=7 && position.endNode().getProperty('user_id')!=5;")
    ->setMaxDepth(3)
    ->setUniqueness(Traversal::UniquenessNodeGlobal)
    ->setOrder(Traversal::OrderBreadthFirst);

使用上面的 Traversal Rest Api 和 Neo4jPHP Traversal 我得到了结果:

9,6,7,3,2,10,5,4,8

虽然我想要的结果是:

6,3,10,4

因为

9,7,2,5,8
已经是该用户的好友:
1

注意:

I just updated the way I traverse my graph to find friends of friends at depth of 3, so I updated my question too.

我们可以看到我在return_filter中设置的条件是手动的:

"body" : "position.endNode().getProperty('user_id')!=1 && position.endNode().getProperty('user_id')!=9 && position.endNode().getProperty('user_id')!=2 && position.endNode().getProperty('user_id')!=8 && position.endNode().getProperty('user_id')!=7 && position.endNode().getProperty('user_id')!=5;"

在 Cypher 中,我们可以轻松删除已经是用户朋友的朋友的朋友:

1
:

WHERE NOT (U)-[:Friend]->(FFFU)

现在,如何在 Traversal Rest Api 中创建类似的条件?

我问是因为文档中没有太多信息。

neo4j traversal neo4jphp
1个回答
1
投票

难道这不应该通过简单地指定来实现:

MATCH (user:User)-[:FRIEND*2..4]->(fof)
WHERE NOT (user)-[:FRIEND]->(fof)

或者也许我遗漏了一些东西,您是否使用 DISTINCT 语句作为提高性能的方法?我很惊讶 cypher 在这里对您来说表现不佳,您可以在 Neo4j shell 中使用 PROFILE 命令尝试查询吗?

对于遍历,从概念上讲,我会这样做:

Start at User
Find all Users friends, and put them in a Set 'friends'
Start at each friend, and traverse out as many hops you like
Return each user found that is not in the set of friends

我不相信你可以在REST遍历API中完成set部分,这意味着你要么需要编写一个服务器扩展,这将允许你用Java编写它并使用更强大的Java遍历API,你可以阅读关于扩展这里:http://docs.neo4j.org/chunked/stable/server-unmanagement-extensions.html和Java遍历API在这里:http://docs.neo4j.org/chunked/stable/tutorial -遍历-java-api.html

或者,您可以执行两个调用,一个用于获取所有用户朋友,另一个用于作为您发送的脚本的一部分与用户朋友进行 REST 遍历,就像您在问题中所做的那样,但您的应用程序生成过滤器代码。

© www.soinside.com 2019 - 2024. All rights reserved.