子句-MATCH

Neo
Neo
2022-03-23 / 0 评论 / 54 阅读

本节内容源自Cypher官方手册V4.4版,笔者对其进行学习、翻译、记录。

简介

MATCH子句允许您指定 Neo4j 将在数据库中搜索的模式,通常与向模式添加限制的WHERE部分联合使用。MATCH查询本身通常不用指定具体执行搜索的算法。Neo4j将自动找出寻找起始节点和匹配模式的最佳方法。

下图用于以下示例:
image.png

基本节点查找

获取所有节点

通过仅指定具有单个节点且没有标签的模式,将返回图中的所有节点。

MATCH (n)
RETURN n
Node[0]{name:"Charlie Sheen"}
Node[1]{name:"Martin Sheen"}
Node[2]{name:"Michael Douglas"}
Node[3]{name:"Oliver Stone"}
Node[4]{name:"Rob Reiner"}
Node[5]{title:"Wall Street"}
Node[6]{title:"The American President"}

返回数据库中的所有节点。

获取所有带有标签的节点

MATCH (movie:Movie)
RETURN movie.title
"Wall Street"
"The American President"

相关节点

该符号--表示相关,而不考虑关系的类型或方向。

MATCH (director {name: 'Oliver Stone'})--(movie)
RETURN movie.title
"Wall Street"

与标签匹配

要使用节点上的标签限制模式,请使用标签语法将其添加到模式节点。

MATCH (:Person {name: 'Oliver Stone'})--(movie:Movie)
RETURN movie.title
"Wall Street"

关系基础

外向关系

当关系的方向感兴趣时,使用-->或者<--表示,如下所示:

MATCH (:Person {name: 'Oliver Stone'})-->(movie)
RETURN movie.title
"Wall Street"

有向关系和变量

如果需要一个变量,无论是为了过滤关系的属性,还是返回关系,这就是你引入变量的方式。

MATCH (:Person {name: 'Oliver Stone'})-[r]->(movie)
RETURN type(r)
"DIRECTED"

匹配关系类型

当您知道要匹配的关系类型时,可以通过使用冒号和关系类型来指定它。

MATCH (wallstreet:Movie {title: 'Wall Street'})<-[:ACTED_IN]-(actor)
RETURN actor.name
"Michael Douglas"
"Martin Sheen"
"Charlie Sheen"

匹配多种关系类型

要匹配多种类型中的一种,您可以通过将它们与管道符号 | 链接在一起来指定它。

MATCH (wallstreet {title: 'Wall Street'})<-[:ACTED_IN|:DIRECTED]-(person)
RETURN person.name
"Oliver Stone"
"Michael Douglas"
"Martin Sheen"
"Charlie Sheen"

匹配关系类型并使用变量

如果您想引入一个变量来保存关系,并指定您想要的关系类型,只需将它们都添加,如下所示:

MATCH (wallstreet {title: 'Wall Street'})<-[r:ACTED_IN]-(actor)
RETURN r.role
"Gordon Gekko"
"Carl Fox"
"Bud Fox"

深度关系

在单个模式中,关系只会匹配一次。

具有不常见字符的关系类型

有时您的数据库将包含非字母字符或其中包含空格的类型。使用`(反引号)引用这些。为了证明这一点,我们可以在'Charlie Sheen'和'Rob Reiner'之间添加一个额外的关系:

MATCH
  (charlie:Person {name: 'Charlie Sheen'}),
  (rob:Person {name: 'Rob Reiner'})
CREATE (rob)-[:`TYPE INCLUDING A SPACE`]->(charlie)

这导致下图:
image.png

MATCH (n {name: 'Rob Reiner'})-[r:`TYPE INCLUDING A SPACE`]->()
RETURN type(r)
"TYPE INCLUDING A SPACE"

多重关系

关系可以用 ()--() 的形式使用多个语句来表示,也可以串在一起,如下所示:

MATCH (charlie {name: 'Charlie Sheen'})-[:ACTED_IN]->(movie)<-[:DIRECTED]-(director)
RETURN movie.title, director.name
"Wall Street"
"Oliver Stone"

可变长度关系

MATCH (charlie {name: 'Charlie Sheen'})-[:ACTED_IN*1..3]-(movie:Movie)
RETURN movie.title
"Wall Street"
"The American President"
"The American President"

具有多种关系类型的可变长度关系

MATCH (charlie {name: 'Charlie Sheen'})-[:ACTED_IN|DIRECTED*2]-(person:Person)
RETURN person.name
"Oliver Stone"
"Michael Douglas"
"Martin Sheen"

变长关系中的关系变量

当两个节点之间的连接长度可变时,可以使用以下语法返回包含该连接的关系列表:

MATCH p = (actor {name: 'Charlie Sheen'})-[:ACTED_IN*2]-(co_actor)
RETURN relationships(p)
[:ACTED_IN[0]{role:"Bud Fox"},:ACTED_IN[2]{role:"Gordon Gekko"}]
[:ACTED_IN[0]{role:"Bud Fox"},:ACTED_IN[1]{role:"Carl Fox"}]

与可变长度路径上的属性匹配

具有在其中定义的属性的可变长度关系意味着路径中的所有关系都必须将属性设置为给定值。在这个查询中, 'Charlie Sheen'和他的父亲'Martin Sheen'之间有两条路径。其中一个包括“阻塞”关系,另一个不包括。在这种情况下,我们首先通过使用以下查询来添加BLOCKED和UNBLOCKED关系来更改原始图:

MATCH
  (charlie:Person {name: 'Charlie Sheen'}),
  (martin:Person {name: 'Martin Sheen'})
CREATE (charlie)-[:X {blocked: false}]->(:UNBLOCKED)<-[:X {blocked: false}]-(martin)
CREATE (charlie)-[:X {blocked: true}]->(:BLOCKED)<-[:X {blocked: false}]-(martin)

这意味着我们从下图开始:
image.png

MATCH p = (charlie:Person)-[* {blocked:false}]-(martin:Person)
WHERE charlie.name = 'Charlie Sheen' AND martin.name = 'Martin Sheen'
RETURN p
(0)-[X,7]->(7)<-[X,8]-(1)

返回'​​Charlie Sheen'和'Martin Sheen'之间的路径,其中所有关系的blocked属性都设置为false。

零长度路径

使用下限为零的可变长度路径意味着两个变量可以指向同一个节点。如果两个节点之间的路径长度为零,则根据定义,它们是同一个节点。请注意,当匹配零长度路径时,即使匹配未使用的关系类型,结果也可能包含匹配项。

MATCH (wallstreet:Movie {title: 'Wall Street'})-[*0..1]-(x)
RETURN x
Node[5]{title:"Wall Street"}
Node[3]{name:"Oliver Stone"}
Node[2]{name:"Michael Douglas"}
Node[1]{name:"Martin Sheen"}
Node[0]{name:"Charlie Sheen"}

命名路径

如果要返回或过滤模式图中的路径,可以引入命名路径。

MATCH p = (michael {name: 'Michael Douglas'})-->()
RETURN p
(2)-[ACTED_IN,2]->(5)
(2)-[ACTED_IN,5]->(6)

在绑定关系上匹配

当您的模式包含绑定关系,并且该关系模式未指定方向时,Cypher 将尝试在两个方向上匹配关系。

MATCH (a)-[r]-(b)
WHERE id(r) = 0
RETURN a, b
Node[0]{name:"Charlie Sheen"}
Node[5]{title:"Wall Street"}
Node[5]{title:"Wall Street"}
Node[0]{name:"Charlie Sheen"}

最短路径

单一最短路径

在两个节点之间找到一条最短路径就像使用该shortestPath函数一样简单。它是这样完成的:

MATCH
  (martin:Person {name: 'Martin Sheen'}),
  (oliver:Person {name: 'Oliver Stone'}),
  p = shortestPath((martin)-[*..15]-(oliver))
RETURN p

这意味着:在两个节点之间找到一条最短路径,只要该路径最长为 15 个关系。在括号内定义路径的单个链接——起始节点、连接关系和结束节点。在寻找最短路径时,都会使用描述关系类型、最大跳数和方向等关系的特征。

(1)-[ACTED_IN,1]->(5)<-[DIRECTED,3]-(3)

带谓词的单一最短路径

WHERE在决定最短匹配路径是什么之前,对应用于最短路径模式的子句中使用的谓词进行评估。

MATCH
  (charlie:Person {name: 'Charlie Sheen'}),
  (martin:Person {name: 'Martin Sheen'}),
  p = shortestPath((charlie)-[*]-(martin))
WHERE none(r IN relationships(p) WHERE type(r) = 'FATHER')
RETURN p
(0)-[ACTED_IN,0]->(5)<-[ACTED_IN,1]-(1)

此查询将找到'Charlie Sheen'和'Martin Sheen'之间的最短路径,并且WHERE谓词将确保我们不考虑两者之间的父子关系。

所有最短路径

查找两个节点之间的所有最短路径。

MATCH
  (martin:Person {name: 'Martin Sheen'} ),
  (michael:Person {name: 'Michael Douglas'}),
  p = allShortestPaths((martin)-[*]-(michael))
RETURN p

查找'Martin Sheen'和'Michael Douglas'之间的两条最短路径。

(1)-[ACTED_IN,1]->(5)<-[ACTED_IN,2]-(2)
(1)-[ACTED_IN,4]->(6)<-[ACTED_IN,5]-(2)

通过id获取节点或关系

按 id 的节点

通过 id 搜索节点可以使用id()函数来完成。

删除节点和关系时,Neo4j重用其内部ID。这意味着使用和依赖内部Neo4j ID的应用程序很脆弱,或者有出错的风险。因此,建议使用应用程序生成的ID。

MATCH (n)
WHERE id(n) = 0
RETURN n
Node[0]{name:"Charlie Sheen"}

多个节点按 id

通过在 IN 子句中指定多个节点来选择它们。

MATCH (n)
WHERE id(n) IN [0, 3, 5]
RETURN n
Node[0]{name:"Charlie Sheen"}
Node[3]{name:"Oliver Stone"}
Node[5]{title:"Wall Street"}