获取所有祖先的一组属性值

时间:2014-12-18 01:31:12

标签: neo4j cypher

我正在尝试找到一种有效的方法来获取节点祖先的一组属性值。考虑以下简单的设置:

CREATE 
(a {id:'a'}), (b {id:'b'}), (c {id:'c'}), (d {id:'d', age:10}),
(b)-[:HAS_PARENT]->(a),
(c)-[:HAS_PARENT]->(a),
(d)-[:HAS_PARENT]->(b),
(d)-[:HAS_PARENT]->(c)

我想在dd之间以及a的其他一些属性中获取ID为d且所有ID的所有ID的集合}。

我想出了这个:

MATCH (d {id:'d'})
OPTIONAL MATCH path=(d)-[:HAS_PARENT*]->()
RETURN d.age as age,
(REDUCE(o = [], r IN (collect (extract (n in nodes(path) | n.id))) | o + r)) AS closure

哪个方法不起作用,因为它不会使closure中的值保持唯一,而且效率也非常低效。如果我不使用此路径匹配,而只是将d的ID设置为项目,然后使用Java API自行执行相同的遍历:

for (Path path: graphDb.traversalDescription()
                .depthFirst()
                .relationships(RealtionshipNames.HAS_PARENT, Direction.OUTGOING)
                .uniqueness(Uniqueness.NODE_GLOBAL)
                .traverse(graphDb.getNodeById(nodeId))) {
    ids.add((String)path.endNode().getProperty("id"))
}

即使使用更大的数据集(100k节点,200k关系),任务也会在几秒钟内完成。通过我的Cypher查询,它永远不会完成。

有没有办法将这一切合并到一个高效的Cypher查询中,还是我最好用Java API进行一些后期处理?

1 个答案:

答案 0 :(得分:2)

如果您现在只想要父母的身份证件:

MATCH (d {id:'d'})
OPTIONAL MATCH path=(d)-[:HAS_PARENT*]->(p)
WHERE NOT (p)-[:HAS_PARENT]->()
RETURN d.age, d.id, collect(NODES(path))

WHERE NOT (p)-[:HAS_PARENT]->()只会将路径一直返回到第一个祖先,而不是中间路径。

对于从d到head祖先的树中的每条路径,这将返回一行,我认为这不是你想要的。您可以将其与UNWIND结合使用WITH语句将唯一ID提取到集合中。

如果你想要的只是那些没有真正关心路径的ID,你可以使用:

MATCH (d { id:'d' })
OPTIONAL MATCH path=(d)-[:HAS_PARENT*]->(p)
RETURN d.id, d.age, COLLECT(DISTINCT p.id)

如果你需要集合中的头部,那么将最后一行改为:

RETURN d.id, d.age, d+ COLLECT(DISTINCT p.id)