neo4j - 查询返回子图和所有内部关系
问题描述
给定下图:
可通过以下 Cypher 脚本创建:
CREATE
(n1:Token {content: "lonely"}),
(n2:Token {content: "island"}),
(n1)-[:PRECEDES]->(n2);
CREATE
(n1:Token {content: "the"}),
(n2:Token {content: "quick"}),
(n3:Token {content: "brown"}),
(n4:Token {content: "fox"}),
(n5:Token {content: "bear"}),
(n1)-[:PRECEDES]->(n2),
(n2)-[:PRECEDES]->(n3),
(n3)-[:PRECEDES]->(n4),
(n3)-[:PRECEDES]->(n5);
我想要一个查询,它将从给定的根返回路径中的节点,向后遵循 PRECEDES 关系。查询还应该返回给定节点的所有传入关系,以便稍后我可以在内存中构造子图。但是,传入关系列表不应指向返回的根之外。
例如,如果我查询 root lonely
,我想要结果:
+-----------------------------------------------------------------------+
| (:Token {content: "lonely"}) | [] |
| (:Token {content: "island"}) | [[:PRECEDES]] |
+-----------------------------------------------------------------------+
如果我查询根the
,我想要结果:
+-----------------------------------------------------------------------+
| (:Token {content: "the"}) | [] |
| (:Token {content: "quick"}) | [[:PRECEDES]] |
| (:Token {content: "brown"}) | [[:PRECEDES]] |
| (:Token {content: "fox"}) | [[:PRECEDES]] |
| (:Token {content: "bear"}) | [[:PRECEDES]] |
+-----------------------------------------------------------------------+
如果我查询 root brown
,我想要以下结果,请注意它brown
本身的传入关系已被省略,因为它会指向子图之外。
+-----------------------------------------------------------------------+
| (:Token {content: "brown"}) | [] |
| (:Token {content: "fox"}) | [[:PRECEDES]] |
| (:Token {content: "bear"}) | [[:PRECEDES]] |
+-----------------------------------------------------------------------+
根节点和叶节点应始终包含在结果中。
这是我迄今为止的尝试:
MATCH (a:Token {content: {root}})-[:PRECEDES*]->(t:Token)
WITH COLLECT(a) + COLLECT(DISTINCT t) AS nodes_
UNWIND nodes_ AS n
OPTIONAL MATCH p = (n)-[r]-()
WITH n AS n2, COLLECT(DISTINCT RELATIONSHIPS(p)) AS nestedrel
RETURN n2, REDUCE(output = [], rel in nestedrel | output + rel) AS rels
这有点接近,但有几个问题:使用COLLECT(a)
来人为地包含根有点 hacky,它会在关系结果中留下指向远离根的关系,并且如果您尝试使用叶节点作为根它根本不会返回任何节点。(这REDUCE
部分只是将关系列表扁平化了一层。)
[仅供参考,应用程序是我需要在内存中重建这个树结构作为 NetworkX MultiDiGraph。]
解决方案
由于您稍后会尝试在内存中重建子图,因此您可以使用APOC 过程 apoc.convert.toTree
并直接返回树结构,而无需进行转换。因此,您可以运行以下查询:
match p = (:Token {content: "the"})-[:PRECEDES*]->(end:Token)
where not (end)-[:PRECEDES]->()
call apoc.convert.toTree([p]) yield value
return value
推荐阅读
- webview - 如何在屏幕更改时处理 Flutter WebviewScaffold?
- c# - ASP.NET Core 2.1 角色管理器注册
- python - 有没有办法从 DataFrame.from_dict 中删除列号和行号?
- tinyos - tinyos 的 C 应用程序
- c# - Add X row with textboxes in Repeater based on input number ASP.NET
- javascript - 如何调整按钮的断点以使它们折叠成一列?
- python - 如何组织具有许多窗口和功能的 Tkinter 代码
- php - Magento 2 无法安装示例数据
- mysql - 对查询中的 SQL 结果进行排序
- ios - Expo-ios / facebook登录不起作用独立应用程序