Cypher:通过关系进行深度优先导航
Cypher: Depth-first navigation through the relationships
在 Neo4j 版本 3.5.6 中,是否有 "Cypher" 以深度优先方式浏览关系的方法?让我用一个简单的例子来解释:
我有标记为 P(人)的节点,可以使用标记为 F(朋友)的关系链接在一起。每个节点 P 都有一个年龄属性(人的年龄)。我需要在每个 P 节点上计算 ages 属性,该属性是一个数组,其中包含该人的年龄和她所有朋友的年龄。
举个例子,我是爱丽丝的朋友,爱丽丝是比尔和乔的朋友。这是构造图形的代码:
create (jp:P{name:"jp", age:35})
create (alice:P{name:"alice", age:32})
create (bill:P{name:"bill", age:25})
create (joe:P{name:"joe", age:42})
create (alice)-[:F]->(bill)
create (alice)-[:F]->(joe)
create (jp)-[:F]->(alice)
我首先检查了默认导航是否(偶然)是深度优先的。首先,我初始化 ages 数组以包含此人的年龄:
match (p:P) set p.ages = [p.age] return p
这 returns 我所期望的:
╒═════════════════════════════════════╕
│"p" │
╞═════════════════════════════════════╡
│{"name":"jp","ages":[35],"age":35} │
├─────────────────────────────────────┤
│{"name":"alice","ages":[32],"age":32}│
├─────────────────────────────────────┤
│{"name":"bill","ages":[25],"age":25} │
├─────────────────────────────────────┤
│{"name":"joe","ages":[42],"age":42} │
└─────────────────────────────────────┘
然后我浏览关系并更新年龄数组:
match (p1)-[:F]->(p2) set p1.ages = p1.ages + p2.ages
查看我得到的结果:
╒═══════════════════════════════════════════╕
│"p" │
╞═══════════════════════════════════════════╡
│{"name":"jp","ages":[35,32],"age":35} │
├───────────────────────────────────────────┤
│{"name":"alice","ages":[32,25,42],"age":32}│
├───────────────────────────────────────────┤
│{"name":"bill","ages":[25],"age":25} │
├───────────────────────────────────────────┤
│{"name":"joe","ages":[42],"age":42} │
└───────────────────────────────────────────┘
看来 alice 的年龄是正确的(她自己的年龄以及 bill 和 joe 的年龄),但 jp 的不正确,它只包含 jp 和 alice 的年龄,不包含 joe 和 bill 的年龄。所以默认导航不是深度优先。
我找到了一种让它工作的方法,尽管缺点是必须对最大深度进行硬编码,并针对每个深度发出一个查询:
match (p:P) set p.ages=[p.age]
match (p1)-[:F*2..2]->(p2) set p1.ages = p1.ages + p2.ages
match (p1)-[:F*1..1]->(p2) set p1.ages = p1.ages + p2.ages
这会产生以下(正确的)结果:
╒═══════════════════════════════════════════╕
│"p" │
╞═══════════════════════════════════════════╡
│{"name":"jp","ages":[35,42,25,32],"age":35}│
├───────────────────────────────────────────┤
│{"name":"alice","ages":[32,42,25],"age":32}│
├───────────────────────────────────────────┤
│{"name":"bill","ages":[25],"age":25} │
├───────────────────────────────────────────┤
│{"name":"joe","ages":[42],"age":42} │
└───────────────────────────────────────────┘
有什么方法可以使用普通的 Cypher 查询(无 Java 代码)来获得相同的结果,而不必对最大深度进行硬编码?
感谢您的帮助!
我刚刚找到了这个问题的简单答案:使用收集结构:
match (a:P)-[:F*0..10]->(b:P) return a.name, collect(b.age) as ages
正确returns:
╒════════╤═════════════╕
│"a.name"│"ages" │
╞════════╪═════════════╡
│"jp" │[35,32,25,42]│
├────────┼─────────────┤
│"alice" │[32,25,42] │
├────────┼─────────────┤
│"bill" │[25] │
├────────┼─────────────┤
│"joe" │[42] │
└────────┴─────────────┘
上面唯一的硬编码信息是最大深度 (10)
在 Neo4j 版本 3.5.6 中,是否有 "Cypher" 以深度优先方式浏览关系的方法?让我用一个简单的例子来解释:
我有标记为 P(人)的节点,可以使用标记为 F(朋友)的关系链接在一起。每个节点 P 都有一个年龄属性(人的年龄)。我需要在每个 P 节点上计算 ages 属性,该属性是一个数组,其中包含该人的年龄和她所有朋友的年龄。
举个例子,我是爱丽丝的朋友,爱丽丝是比尔和乔的朋友。这是构造图形的代码:
create (jp:P{name:"jp", age:35})
create (alice:P{name:"alice", age:32})
create (bill:P{name:"bill", age:25})
create (joe:P{name:"joe", age:42})
create (alice)-[:F]->(bill)
create (alice)-[:F]->(joe)
create (jp)-[:F]->(alice)
我首先检查了默认导航是否(偶然)是深度优先的。首先,我初始化 ages 数组以包含此人的年龄:
match (p:P) set p.ages = [p.age] return p
这 returns 我所期望的:
╒═════════════════════════════════════╕
│"p" │
╞═════════════════════════════════════╡
│{"name":"jp","ages":[35],"age":35} │
├─────────────────────────────────────┤
│{"name":"alice","ages":[32],"age":32}│
├─────────────────────────────────────┤
│{"name":"bill","ages":[25],"age":25} │
├─────────────────────────────────────┤
│{"name":"joe","ages":[42],"age":42} │
└─────────────────────────────────────┘
然后我浏览关系并更新年龄数组:
match (p1)-[:F]->(p2) set p1.ages = p1.ages + p2.ages
查看我得到的结果:
╒═══════════════════════════════════════════╕
│"p" │
╞═══════════════════════════════════════════╡
│{"name":"jp","ages":[35,32],"age":35} │
├───────────────────────────────────────────┤
│{"name":"alice","ages":[32,25,42],"age":32}│
├───────────────────────────────────────────┤
│{"name":"bill","ages":[25],"age":25} │
├───────────────────────────────────────────┤
│{"name":"joe","ages":[42],"age":42} │
└───────────────────────────────────────────┘
看来 alice 的年龄是正确的(她自己的年龄以及 bill 和 joe 的年龄),但 jp 的不正确,它只包含 jp 和 alice 的年龄,不包含 joe 和 bill 的年龄。所以默认导航不是深度优先。
我找到了一种让它工作的方法,尽管缺点是必须对最大深度进行硬编码,并针对每个深度发出一个查询:
match (p:P) set p.ages=[p.age]
match (p1)-[:F*2..2]->(p2) set p1.ages = p1.ages + p2.ages
match (p1)-[:F*1..1]->(p2) set p1.ages = p1.ages + p2.ages
这会产生以下(正确的)结果:
╒═══════════════════════════════════════════╕
│"p" │
╞═══════════════════════════════════════════╡
│{"name":"jp","ages":[35,42,25,32],"age":35}│
├───────────────────────────────────────────┤
│{"name":"alice","ages":[32,42,25],"age":32}│
├───────────────────────────────────────────┤
│{"name":"bill","ages":[25],"age":25} │
├───────────────────────────────────────────┤
│{"name":"joe","ages":[42],"age":42} │
└───────────────────────────────────────────┘
有什么方法可以使用普通的 Cypher 查询(无 Java 代码)来获得相同的结果,而不必对最大深度进行硬编码?
感谢您的帮助!
我刚刚找到了这个问题的简单答案:使用收集结构:
match (a:P)-[:F*0..10]->(b:P) return a.name, collect(b.age) as ages
正确returns:
╒════════╤═════════════╕
│"a.name"│"ages" │
╞════════╪═════════════╡
│"jp" │[35,32,25,42]│
├────────┼─────────────┤
│"alice" │[32,25,42] │
├────────┼─────────────┤
│"bill" │[25] │
├────────┼─────────────┤
│"joe" │[42] │
└────────┴─────────────┘
上面唯一的硬编码信息是最大深度 (10)