从cypher中的多个特定路径查询节点

时间:2014-07-11 14:06:32

标签: neo4j cypher

我正在玩cypher,我会为我做一些简单的聚合。

MATCH (p:Person)-[:HAS_CAR]->(n:Car)
RETURN n, count(p)

MATCH (p:Person)-[:HAS_APARTMENT]->(n:Apartment)
RETURN n, count(p)

MATCH (p:Person)-[:HAS_HOUSE]->(n:House)
RETURN n, count(p)

问题是我必须进行3次数据库访问以获得所有这些结果。有问题的是,这些查询是更大链中的最后一个MATCH语句。像这样:

MATCH (:City { Id: 10})<-[:LIVES_IN]-(p:Person)
WITH p
MATCH ...
WITH p
MATCH ...
WITH p
MATCH ...
WITH p
MATCH ...
WITH p
MATCH p-[:HAS_CAR]->(n:Car)
RETURN n, count(p)

在所有这些MATCH ... WITH语句之后,只有少数人节点匹配,因此查询的最后部分非常快,但初始部分不是。我无能为力,但认为这可以改进,因为所有三个查询共享很多陈述。

我想出了这个:

...
MATCH p-[:HAS_CAR|HAS_APARTMENT|HAS_HOUSE]->(n)
RETURN n, labels(n), count(p)

我可以解决这个问题。但是,如果我想混合这样的东西怎么办:

MATCH p-[:KNOWS]->(:Person)-[:HAS_BIKE]->(n:Bike)
RETURN n, count(p)

甚至:

MATCH p-[:KNOWS]->(:Person)-[:HAS_BIKE|HAS_BOAT]->(n)
RETURN n, labels(n), count(p)

所有这些都可以在一个查询中完成吗?

1 个答案:

答案 0 :(得分:2)

有时您需要使用集合而不是行来将聚合查询合并在一起并传递它们。这个策略可能会有所帮助......例如:

MATCH (p:Person)-[:HAS_CAR]->(car:Car)
WITH car, count(p) carCount
WITH collect({car:car, count:carCount}) as carCounts
MATCH (p:Person)-[:HAS_APARTMENT]->(n:Apartment)
WITH n, count(p) as apartmentCount, carCounts
RETURN collect({apartment:n, count:apartmentCount}) as apartmentCounts, carCounts

更新(请参阅评论) - 这可让您传递过滤器的结果并执行快速ID查找以再次找到它们:

MATCH (p:Person)
WHERE p.name = "John" // or whatever else you need to filter on
WITH collect(id(p)) as pids
MATCH (p)-[:HAS_CAR]->(car:Car)
WHERE id(p) IN pids
WITH car, count(p) carCount, pids
WITH collect({car:car, count:carCount}) as carCounts, pids
MATCH (p)-[:HAS_APARTMENT]->(n:Apartment)
WHERE id(p) IN pids
WITH n, count(p) as apartmentCount, carCounts
RETURN collect({apartment:n, count:apartmentCount}) as apartmentCounts, carCounts