【问题标题】:Filtering incoming nodes in Neo4J based on a node filtering property upstream根据上游的节点过滤属性过滤 Neo4J 中的传入节点
【发布时间】:2018-08-27 19:14:04
【问题描述】:

在处理 rdbms 数据沿袭项目时,我遇到了我无法解决的 Neo4J Cypher 挑战:

这是一个例子:

  1. 图表由表示数据库表(标签:TABLE)或视图(标签:VIEW)的节点组成
  2. 表格或其他视图通过方向 -[:SOURCES]-> 关系获取视图
  3. 图表的一个子集有 10 个 TABLE 节点,可以选择过滤(从图表中排除)。它们通过 name 属性命名为 A1 到 A10。这些节点具有附加标签FILTERNODE
  4. 这 10 个节点通过 SOURCES 关系链接到 VIEW 节点 B,示例A1-[:SOURCES]->B
  5. 节点 B 依次获取 VIEW 节点 C:B-[:SOURCES]->C
  6. 节点 C 有一个用于过滤的数组属性:C.filter=['A2','A3']
  7. 节点 C 依次源 VIEW 节点 D:B-[:SOURCES]->C

现在我想查询从 A* 节点到 D 的链,不显示所有 A* 节点,而只显示节点 C 上的 filter 属性过滤的那些。

我想这需要分多个步骤完成:

  1. 首先选择整个子图,包含 A1..A10,B,C,D
  2. 然后从这个子图中唯一地收集所有过滤属性
  3. 在具有 FILTERNODE 属性的节点上使用收集的过滤属性,仅保留 A2、A3、B、C 和 D

如何在 Cypher 中实现这一点?

【问题讨论】:

  • 您对此查询的输入是什么?您是从标识节点 C(或 D?)的东西开始,还是您的意思是查询一个没有传出 :SOURCES 关系的节点,找到它的过滤器,并将路径匹配回这些源?还是另一种方法?
  • 我将图形“返回”到输入源,意思是:从节点 C 开始,到节点 B(指向 c 的源),到节点 A1..10,每个源都指向 B。但是而不是显示 A1 到 A10 节点我只想显示 A2 和 A3(因为节点 C 上的过滤器属性)
  • 好的,听起来不错。你在这里使用什么标签?源节点(您的 A 节点)是否有一组通用标签?
  • 是的,A 节点都有 :TABLE 标签。 C.filter 属性中的值将是这些节点的唯一键(它们的 name 属性)
  • 所以,我仍然对你想要什么感到有些困惑。听起来您想要MATCH (c{id:"start"}), (a) WHERE a.name in c.filters 之类的东西,也许AND (a)-[:SOURCES*]->(c) 来仔细检查它们实际上是连接的(当然在a.name 上有一个索引)。也许还有一个额外的OPTIONAL MATCH (a)-[:SOURCES*]->(b)-[:SOURCES*]->(c) 来接听中间的内容。对于奖金挑战,是说 C 也可以过滤上游吗?我读到这篇文章的另一种方式是你想收集图中的所有过滤器,然后返回过滤器中的所有节点,以及它们之间的节点。

标签: neo4j cypher


【解决方案1】:

这是密码reference card;但基本上你想从属性中收集多个数组,将它们组合成一个列表,然后将其用作过滤器。您需要将所有内容组合到一个列表中的主要内容是 EXTRACT+REDUCE,并带有一个过滤器来保护自己免受空值的影响(未设置属性)。

这是一个 Cypher,展示了如何将提取 + 减少作为一个干净的步骤,cmets 解释了 Cypher 的每个步骤。

// Match our starting point, and collect all child views (0.. collects itself too)
MATCH (:TABLE)-[:SOURCES]->(start:View)-[:SOURCES*0..25]->(view:View)
// Make sure we only have one copy of each view
WITH COLLECT(DISTINCT view) as views
// Collect all filters (if they exist) into one list
WITH views, reduce(s = [], v IN [x IN views WHERE EXISTS(x.filter) | x.filter]| s + v.filter) as filters
// Match all tables in filter list
MATCH (a:TABLE)
WHERE a.name IN filters
// Format return; Everything in one column
WITH views+COLLECT(a) as ns
UNWIND ns as n
RETURN n

【讨论】:

  • 哈,这看起来像是我可以使用的东西,我的密码不是那么先进(还),但我明白你在做什么!
【解决方案2】:

所以你从一个特定的节点 C 开始,需要遍历并获取充当源的 :TABLE 节点,但只有那些由 C 上的列表属性过滤的节点。

这应该可行:

MATCH (c)
WHERE id(c) = 123 // standin for however you match to your starting node
WITH c, c.filter as allowed
MATCH (a:TABLE)-[:SOURCES*]->(c)
WHERE a.name in allowed
RETURN a

如果您有很多输入节点,并且 :TABLE(name) 是唯一的,那么我们可以将其修改为对可能的输入节点进行预匹配,让我们进行节点比较而不是属性比较:

MATCH (c)
WHERE id(c) = 123 // standin for however you match to your starting node
MATCH (a:TABLE)
WHERE a.name in c.filter
WITH c, collect(a) as allowed
MATCH (a:TABLE)-[:SOURCES*]->(c)
WHERE a in allowed
RETURN a

【讨论】:

  • 嗨,这不是我想要的,请参阅我更改的问题/试图使其更清楚。仅供参考,过滤属性可以在子图中的任何位置,我不知道它在 C 中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-02
  • 1970-01-01
相关资源
最近更新 更多