【问题标题】:Is there any way to differentiate some nodes returned by a cypher query?有没有办法区分密码查询返回的某些节点?
【发布时间】:2018-07-18 12:55:08
【问题描述】:

我使用 Neo4j 图形数据库。 我的查询从我知道的起始节点(以某种方式遍历图)中查找节点,作为查询的参数。

我想标记这些起始节点,因为我的查询可以在返回图的另一部分多次返回这些相同的节点。

这是一个假的虚拟查询示例:

MATCH (n0 {name:"john"}), (n1 {name:"doe"})
WITH n0, n1
MATCH p=((P)-[:LINK*1..5]->(n0)-[:LINK]->(n1)->[:LINK*1..5]->(N))
WITH collect(P) + collect(N) + n0 as nodes
RETURN nodes;

我希望 n0 和 n1 具有一些特殊的东西,一个新属性,因为结果可以包含具有相同属性/名称的其他节点。

最好用数组来组织结果,如下图:

[
  [P0, P1, P2, P3],
  [n0, n1],           <--- The 2 starting nodes in the middle !
  [N0, N1, N2, N3]
]

是否可以在不更新数据库的情况下从结果中标记部分节点?

【问题讨论】:

    标签: node.js graph neo4j cypher graph-traversal


    【解决方案1】:

    是的,您可以将 labels 添加到这些节点,例如 :StartNode 或 :Start 或类似的。

    事实上,您应该已经在图表中使用了标签,通常当我们看到没有标签的查询时这是一个错误,因为这需要扫描所有节点。请根据节点在图表中的一个或多个角色(例如 :Person、:Movie 或类似)标记您的节点,并确保您在查询中也使用了适当的标签。

    为了添加indexes and constraints,还需要标签,这也可能会加快您的查询速度。

    节点可以是多标签的,因此此时您可以添加更多特定标签以支持特殊情况,例如您在此处需要的。如果您在这些节点上添加 :StartNode 标签,然后在查询中使用该标签,那么这将在所有 :StartNode 标记节点上使用标签扫描,如果这些是唯一具有此标签的节点,那么您的查找将很快。

    【讨论】:

      【解决方案2】:

      我建议重组您的查询以返回您需要知道的最低要求(为了性能和易用性)。

      在您的情况下,您有 2 个不同的 Cyphers(这里它们是最简单的形式)

      MATCH (n0 {name:"john"})-[:LINK]->(n1 {name:"doe"})-[:LINK]->()
      MATCH (P)-[:LINK*1..5]->(n0)
      RETURN COLLECT(P);
      

      MATCH ()-[:LINK]->(n0 {name:"john"})-[:LINK]->(n1 {name:"doe"})
      MATCH (n1)->[:LINK*1..5]->(N)
      RETURN COLLECT(N);
      

      使用相同的起始 MATCH 断言 :LINK 存在。它们是不同的,因为这两个查询没有任何区别。因此,您组合它们的方式将返回这两个密码的笛卡尔积。

      您可以使用 WITH 组合这两个密码以避免创建笛卡尔积

      MATCH (n0 {name:"john"})-[:LINK]->(n1 {name:"doe"})
      MATCH (P)-[:LINK*1..5]->(n0)
      WITH COLLECT(P) as p, n0, n1;
      MATCH (n1)->[:LINK*1..5]->(N)
      RETURN [p, [n0, n1], COLLECT(N)] as nodes
      // Or you could keep the return more normal like this
      // RETURN p, n0, n1, COLLECT(N) as n
      

      现在,如果您真的想像在问题中提出的那样标记节点,您可以将所有节点的数据复制到地图中并标记地图...

      MATCH (n0 {name:"john"})-[:LINK]->(n1 {name:"doe"})
      MATCH (P)-[:LINK*1..5]->(n0)
      WITH COLLECT({labels:LABELS(P), properties:PROPERTIES(P), id:ID(P), mark:"P"}) as p, n0, n1;
      MATCH (n1)->[:LINK*1..5]->(N)
      RETURN [p, [n0, n1], COLLECT({labels:LABELS(N), properties:PROPERTIES(N), id:ID(N), mark:"N"})] as nodes
      

      但是,当您最终复制整个数据集并进行细微的更改时,这通常表明您正在使事情变得比需要的更复杂。此外,在这种情况下,“标记”是完全多余的,因为所有内容都已按列分隔(标记)。

      【讨论】:

      • 问题的查询有 2 个约束:n0 必须有一个传入的 LINKn1 必须有一个传出的 LINK。建议的两个查询不会同时强制执行这两个约束。
      • @cybersam 该约束由第二个匹配项强制执行。如果失败,在 COLLECT 有机会做这件事之前,他们将剩下 0 行。从技术上讲,他们确实相互作用,如果他们不匹配,一方可以歼灭另一方。所以组合形式在技术上稍微更正确。无论如何,我都会添加匹配的缺失部分,以便它们都是正确的。
      猜你喜欢
      • 2020-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-04
      • 2020-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多