Neo4j和Cypher:匹配与目标节点具有单一关系的节点
我试图识别只有一个给定类型关系的节点 想象一个路由和停止节点图。一条路线可以有0个或多个站点,一个站点可以在多条路线之间共享,一个站点必须始终至少有一条路线。我想匹配并删除在删除给定路线时将成为孤立站点的站点 在任何人开口之前,我知道在删除路线后,只找到没有路线的站点会更容易,但这不是一个选项。我们也不担心删除这里的路线,只担心站点 我的问题是:Neo4j和Cypher:匹配与目标节点具有单一关系的节点,neo4j,cypher,Neo4j,Cypher,我试图识别只有一个给定类型关系的节点 想象一个路由和停止节点图。一条路线可以有0个或多个站点,一个站点可以在多条路线之间共享,一个站点必须始终至少有一条路线。我想匹配并删除在删除给定路线时将成为孤立站点的站点 在任何人开口之前,我知道在删除路线后,只找到没有路线的站点会更容易,但这不是一个选项。我们也不担心删除这里的路线,只担心站点 我的问题是: MATCH (r1:Route { id: {route_id} })-[rel1:HAS_STOP]->(s:Stop) MATCH (r2:
MATCH (r1:Route { id: {route_id} })-[rel1:HAS_STOP]->(s:Stop)
MATCH (r2:Route)-[rel2:HAS_STOP]->(s)
WITH s, COUNT(rel2) as c
WHERE c = 1
MATCH s-[rel2]-()
DELETE s, rel2
这个很好用。。。但是有更好的办法吗?感觉它可以更高效,但我不确定如何操作。EDIT
此处的查询只匹配将孤立的节点,而不删除当前路由:
MATCH (route:Route {id:'99e08bdf-130f-3fca-8292-27d616fa025f'})
WITH route
OPTIONAL MATCH (route)-[r:HAS_STOP]->(s)
WHERE NOT EXISTS((route)--(s)<-[:HAS_STOP]-())
DELETE r,s
以下是我的分析查询:
neo4j-sh (?)$ PROFILE MATCH (route:Route {id:'1c565ac4-b72b-37c3-be7f-a38f2a7f66a8'})
> WITH route
> MATCH (route)-[r:HAS_STOP]->(s)
> WITH route, r, collect(s) as stops
> DELETE r, route
> WITH filter(x in stops WHERE NOT x--()) as orphans
> UNWIND orphans as orphan
> DELETE orphan;
+-------------------+
| No data returned. |
+-------------------+
Nodes deleted: 2
Relationships deleted: 157
EmptyResult
|
+UpdateGraph(0)
|
+UNWIND
|
+ColumnFilter(0)
|
+Eager
|
+Extract
|
+UpdateGraph(1)
|
+ColumnFilter(1)
|
+EagerAggregation
|
+SimplePatternMatcher
|
+SchemaIndex
+----------------------+------+--------+--------------+------------------------------+
| Operator | Rows | DbHits | Identifiers | Other |
+----------------------+------+--------+--------------+------------------------------+
| EmptyResult | 0 | 0 | | |
| UpdateGraph(0) | 1 | 1 | | DeleteEntity |
| UNWIND | 1 | 0 | | |
| ColumnFilter(0) | 157 | 0 | | keep columns orphans |
| Eager | 157 | 0 | | |
| Extract | 157 | 0 | | orphans |
| UpdateGraph(1) | 157 | 158 | | DeleteEntity; DeleteEntity |
| ColumnFilter(1) | 157 | 0 | | keep columns route, r, stops |
| EagerAggregation | 157 | 0 | | route, r |
| SimplePatternMatcher | 157 | 0 | route, s, r | |
| SchemaIndex | 1 | 2 | route, route | { AUTOSTRING0}; :Route(id) |
+----------------------+------+--------+--------------+------------------------------+
Total database accesses: 161
您的查询:
MATCH (route:Route {id:'e70ea0d4-03e2-3ca4-afc0-dfdc1754868e'})
WITH route
MATCH (route)-[r:HAS_STOP]->(s)
WITH r, collect(s) as stops
DELETE r, route
WITH filter(x in stops WHERE NOT x--()) as orphans
UNWIND orphans as orphan
DELETE orphan
我稍微修改了您的查询以使用模式索引
这是您的查询的执行计划,数据库访问的差异非常大
PROFILE MATCH (r1:Route { id: '1c565ac4-b72b-37c3-be7f-a38f2a7f66a8' })
> WITH r1
> MATCH (r1)-[rel1:HAS_STOP]->(s:Stop)
> MATCH (r2:Route)-[rel2:HAS_STOP]->(s)
> WITH s, COUNT(rel2) as c
> WHERE c = 1
> MATCH s-[rel2]-()
> DELETE s, rel2;
+-------------------+
| No data returned. |
+-------------------+
Nodes deleted: 1
Relationships deleted: 1
EmptyResult
|
+UpdateGraph
|
+Eager
|
+SimplePatternMatcher(0)
|
+Filter(0)
|
+ColumnFilter
|
+EagerAggregation
|
+Filter(1)
|
+SimplePatternMatcher(1)
|
+Filter(2)
|
+SimplePatternMatcher(2)
|
+SchemaIndex
+-------------------------+------+--------+-----------------------+-----------------------------+
| Operator | Rows | DbHits | Identifiers | Other |
+-------------------------+------+--------+-----------------------+-----------------------------+
| EmptyResult | 0 | 0 | | |
| UpdateGraph | 1 | 2 | | DeleteEntity; DeleteEntity |
| Eager | 1 | 0 | | |
| SimplePatternMatcher(0) | 1 | 0 | UNNAMED200, s, rel2 | |
| Filter(0) | 1 | 0 | | c == { AUTOINT1} |
| ColumnFilter | 157 | 0 | | keep columns s, c |
| EagerAggregation | 157 | 0 | | s |
| Filter(1) | 4797 | 4797 | | hasLabel(r2:Route(4)) |
| SimplePatternMatcher(1) | 4797 | 4797 | r2, s, rel2 | |
| Filter(2) | 157 | 157 | | hasLabel(s:Stop(3)) |
| SimplePatternMatcher(2) | 157 | 157 | r1, s, rel1 | |
| SchemaIndex | 1 | 2 | r1, r1 | { AUTOSTRING0}; :Route(id) |
+-------------------------+------+--------+-----------------------+-----------------------------+
Total database accesses: 9912
真有趣,谢谢!不过,我在帖子中提到,我只需要删除站点,而不需要删除路线。这是销毁前
回调的一部分,因此路由需要保留到最后,因为可能会遇到其他类似的查询。哈哈,好吧,没赶上:)非常酷,谢谢!简单得多。早期的基准测试表明,您的速度确实比预期的更快。:-)现在,从创业板内部找出最好的方法。这将是一个很酷的功能,当它完成。
PROFILE MATCH (r1:Route { id: '1c565ac4-b72b-37c3-be7f-a38f2a7f66a8' })
> WITH r1
> MATCH (r1)-[rel1:HAS_STOP]->(s:Stop)
> MATCH (r2:Route)-[rel2:HAS_STOP]->(s)
> WITH s, COUNT(rel2) as c
> WHERE c = 1
> MATCH s-[rel2]-()
> DELETE s, rel2;
+-------------------+
| No data returned. |
+-------------------+
Nodes deleted: 1
Relationships deleted: 1
EmptyResult
|
+UpdateGraph
|
+Eager
|
+SimplePatternMatcher(0)
|
+Filter(0)
|
+ColumnFilter
|
+EagerAggregation
|
+Filter(1)
|
+SimplePatternMatcher(1)
|
+Filter(2)
|
+SimplePatternMatcher(2)
|
+SchemaIndex
+-------------------------+------+--------+-----------------------+-----------------------------+
| Operator | Rows | DbHits | Identifiers | Other |
+-------------------------+------+--------+-----------------------+-----------------------------+
| EmptyResult | 0 | 0 | | |
| UpdateGraph | 1 | 2 | | DeleteEntity; DeleteEntity |
| Eager | 1 | 0 | | |
| SimplePatternMatcher(0) | 1 | 0 | UNNAMED200, s, rel2 | |
| Filter(0) | 1 | 0 | | c == { AUTOINT1} |
| ColumnFilter | 157 | 0 | | keep columns s, c |
| EagerAggregation | 157 | 0 | | s |
| Filter(1) | 4797 | 4797 | | hasLabel(r2:Route(4)) |
| SimplePatternMatcher(1) | 4797 | 4797 | r2, s, rel2 | |
| Filter(2) | 157 | 157 | | hasLabel(s:Stop(3)) |
| SimplePatternMatcher(2) | 157 | 157 | r1, s, rel1 | |
| SchemaIndex | 1 | 2 | r1, r1 | { AUTOSTRING0}; :Route(id) |
+-------------------------+------+--------+-----------------------+-----------------------------+
Total database accesses: 9912