我正在使用Neo4J并学习Cypher,并且有一个关于根据给定类型的第一个遇到节点的属性过滤结果的问题(在下面的示例代码的OPTIONAL MATCH
行中)。
我的查询如下:
MATCH
(a:Word),
(b:Word)
WHERE a.lemma IN [ "enjoy" ]
AND b.lemma IN [ "control", "achievement" ]
OPTIONAL MATCH p = shortestPath((a)-[:IS_DEFINED_AS|IS_A_FORM_OF*..15]-(b))
RETURN
a.lemma as From, b.lemma as To,
length(
filter(n in nodes(p) WHERE 'Word' in labels(n))
) - 1 as Shortest_Number_of_Hops_Only_Counting_Words,
length(p) as Shortest_Number_of_Hops_Counting_All_Nodes
数据库中可能出现两种常见类型的路径:
(a:Word) <-[IS_A_FORM_OF]- (Morph) -[IS_A_FORM_OF]-> (Word) -[IS_DEFINED_AS]-> (Synset) <-[IS_DEFINED_AS]- (Word) -[IS_DEFINED_AS]-> (Synset) <-[IS_DEFINED_AS]- (b:Word)
和
(a:Word) -[IS_DEFINED_AS]-> (Synset) <-[IS_DEFINED_AS]- (Word) -[IS_DEFINED_AS]-> (Synset) <-[IS_DEFINED_AS]- (b:Word)
a
和b
之间可能有任意数量的跃点(目前在查询中上限为15)。
我试图在上面给出一个非常具体的示例,但我的问题确实是一个关于使用Cypher的非常普遍的问题:我想过滤遇到的第一个Synset节点包含某些路径的路径属性(例如,{part_of_speech: 'verb'}
。我一直在阅读Cypher refcard,我想知道是否应使用head()
表达式以某种方式选择第一个Synset节点路径,但我不确定该怎么做。有没有一种直接的方法将它添加到MATCH / WHERE语句中?
答案 0 :(得分:0)
您可以按照此属性
匹配Synset节点MATCH (verb:Synset {part_of_speech: 'verb'})
RETURN verb
然后变量verb
将仅匹配part_of_speech
属性为"verb"
的Synset节点。
您可以在请求中进一步使用此变量。例如,您可以编写基本相同的请求,限制WHERE
部分中节点属性的值:
MATCH (verb:Synset)
WHERE verb.part_of_speech = 'verb'
RETURN verb
根据您的要求申请,您可以像这样重写:
MATCH
(a:Word) -[:IS_DEFINED_AS]-> (verb:Synset {part_of_speech: "verb"}),
(b:Word)
WHERE a.lemma IN [ "enjoy" ]
AND b.lemma IN [ "control", "achievement" ]
OPTIONAL MATCH p = shortestPath((a)-[:IS_DEFINED_AS]-(verb)-[:IS_DEFINED_AS|IS_A_FORM_OF*..15]-(b))
RETURN
a.lemma as From, b.lemma as To,
length(
filter(n in nodes(p) WHERE 'Word' in labels(n))
) - 1 as Shortest_Number_of_Hops_Only_Counting_Words,
length(p) as Shortest_Number_of_Hops_Counting_All_Nodes
答案 1 :(得分:0)
@ oleg-kurbatov的回答shortestPath()
时不允许指定多个特定的跃点:
MATCH
(a:Word),
(b:Word)
WHERE a.lemma IN [ "enjoy" ]
AND b.lemma IN [ "control", "achievement" ]
MATCH p1 = (a)-[:IS_DEFINED_AS]-> (initial_synset:Synset{pos: 'v'})
OPTIONAL MATCH p2 = shortestPath((initial_synset)-[:IS_DEFINED_AS|IS_A_FORM_OF*..15]-(b))
RETURN
a.lemma as From, b.lemma as To,
length(
filter(n in nodes(p2) WHERE 'Word' in labels(n))
) as Shortest_Number_of_Hops_Only_Counting_Words,
length(p1) + length(p2) as Shortest_Number_of_Hops_Counting_All_Nodes
以Oleg的建议作为起点,我确实找到了一种方法来过滤shortestPath()
,以便它只能在第一个遇到Synset节点的'pos'属性'v'的路径上找到,不增加查询执行时间:我将原始问题中的OPTIONAL MATCH
行修改为:
OPTIONAL MATCH p = shortestPath((a)-[:IS_DEFINED_AS|IS_A_FORM_OF*..15]-(b))
WHERE head(filter(x in nodes(p) WHERE x:Synset)).pos = 'v'
据我所知,filter(x in nodes(p) WHERE x:Synset)
获取了所考虑路径中所有Synset类型节点的列表。 head(...)
从该列表中获取第一个节点,.pos = 'v'
检查该节点的“pos”属性是否为“v”。