【问题标题】:Getting number of unique paths traversed while traversing using Neo4j traversal API使用 Neo4j 遍历 API 获取遍历的唯一路径数
【发布时间】:2017-02-15 14:01:22
【问题描述】:

我创建了以下基本图表:

CREATE (:NodeType1 {prop1:'value1'})-[:RelType1 {prop2:'value2'}]->(:NodeType2 {prop3:'value3'})-[:RelType2 {prop4:'value4'}]->(:NodeType3 {prop5:'value5'})-[:RelType3 {prop6:'value6'}]->(:NodeType4 {prop7:'value7'})

CREATE (:NodeType1 {prop1:'value8'})-[:RelType1 {prop2:'value9'}]->(:NodeType2 {prop3:'value10'})-[:RelType2 {prop4:'value11'}]->(:NodeType3 {prop5:'value12'})-[:RelType3 {prop6:'value13'}]->(:NodeType4 {prop7:'value14'})

MATCH path=(n:NodeType1 {prop1:'value1'})-[*]->(m:NodeType4 {prop7:'value7'})
CREATE (n)-[:RelType1 {prop2:'value15'}]->(:NodeType2 {prop3:'value16'})-[:RelType2 {prop4:'value17'}]->(:NodeType3 {prop5:'value18'})-[:RelType3 {prop6:'value19'}]->(m)

图表如下所示:

当我运行以下密码时:

MATCH path=(a:NodeType1 {prop1:"value1"})-[:RelType1]->(b)-[:RelType2]->(c)-[:RelType3]->(d)
RETURN count(nodes(path))

我得到2 作为输出。似乎nodes() 实际上并没有返回路径中的节点数,而只是返回结果中的行数,因为如果我返回path

MATCH path=(a:NodeType1 {prop1:"value1"})-[:RelType1]->(b)-[:RelType2]->(c)-[:RelType3]->(d)
RETURN path

我在返回的结果中有两行:

现在我猜想如何在使用 Neo4J 遍历 API 进行遍历时获得相同的输出。我得到密码中唯一节点的数量如下:

MATCH path=(a:NodeType1 {prop1:"value1"})-[:RelType1]->(b)-[:RelType2]->(c)-[:RelType3]->(d)
RETURN size(collect(distinct a))+size(collect(distinct b))+size(collect(distinct c))+size(collect(distinct d))

以上查询正确返回6

同样可以在遍历 API 中通过在路径扩展器中使用静态计数器来完成,每次调用 expand() 时都会递增。 (有没有更好的方法呢?)

public class MyPathExpander implements PathExpander{
    static int nodeCount = 0;

    @Override
    public Iterable expand(Path path, BranchState state) {
        Node lastNode = path.endNode();

        nodeCount++;  //**increment the count of nodes visited

        if(lastNode.hasLabel(MyLabels.NodeType1))
            return lastNode.getRelationships(MyRelations.RelType1, Direction.OUTGOING);
        else if (lastNode.hasRelationship(MyRelations.RelType1, Direction.INCOMING))
            return lastNode.getRelationships(MyRelations.RelType2, Direction.OUTGOING);
        else if (lastNode.hasRelationship(MyRelations.RelType2, Direction.INCOMING))
            return lastNode.getRelationships(MyRelations.RelType3, Direction.OUTGOING);
        else if (lastNode.hasRelationship(MyRelations.RelType3, Direction.INCOMING))
            return null;
        return null;
    }
}

但是我想不出方法可以告诉我在使用 Traversal API(相当于上面的RETURN count(nodes(path)))时遍历期间遵循的唯一路径的数量。我怎样才能做到这一点?遍历API不可能吗?

PS:唯一路径是指遍历时访问的节点顺序的唯一排列。例如,所有a-b-ca-c-ba-b-c-d 都是唯一的。

【问题讨论】:

  • nodes(path) 从路径返回节点数组,而不是节点数...

标签: neo4j cypher neo4j-traversal-api


【解决方案1】:

此查询不返回唯一路径的计数,而是查询返回的所有路径的计数:

MATCH path=(a:NodeType1 {prop1:"value1"})-[:RelType1]->(b)
           -[:RelType2]->(c)-[:RelType3]->(d)
RETURN count(nodes(path))

如果要统计查询中唯一节点的数量,可以这样做:

MATCH path=(a:NodeType1 {prop1:"value1"})-[:RelType1]->(b)
           -[:RelType2]->(c)-[:RelType3]->(d)
UNWIND nodes(path) AS N
RETURN count(distinct N)

计算唯一路径数量的一种方法是(对于每个路径计算其唯一指纹,通过遍历 API 重复并不难):

MATCH path=(a:NodeType1 {prop1:"value1"})-[:RelType1]->(b)
           -[:RelType2]->(c)-[:RelType3]->(d)
WITH path, 
     REDUCE(acc="", x in nodes(path) | acc + id(x)) +
     REDUCE(acc="", x in rels(path) | acc + id(x)) as uniID    
RETURN count(distinct uniID)

【讨论】:

  • 密码返回的路径数和唯一路径数是否会有所不同。我觉得两者永远都是一样的。
  • RETURN nodes(path) 返回路径数也很奇怪,尤其是当RETURN path,nodes(path) 正确返回path,nodes 时。但是RETURN path,count(nodes(path)) 返回path,1,即所有路径的1。因此,我尝试通过以下方式获取路径中的节点数:RETURN path,COUNT(UNWIND nodes(path))。它给出了错误。我知道我们可以这样做:RETURN path,length(path)+1 作为节点数 = 1+ 关系数 & length(path) 返回关系数。但是我们可以用COUNT(UNWIND nodes(path))来做吗?这样我们就可以做COUNT(distinct UNWIND nodes(path))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-15
相关资源
最近更新 更多