NEO4J-Cypher图数据库查询语言(3)

2,009 阅读8分钟

Cypher图数据库查询语言(1) :Cypher概述

Cypher图数据库查询语言(2) :Cypher基本语法

Cypher图数据库查询语言(3) :Cypher语句-MATCH,OPTIONAL MATCH

Cypher图数据库查询语言(4) :Cypher语句-WHERE

Cypher图数据库查询语言(5) :Cypher语句-START,Aggregation 和 LOAD CSV

Cypher图数据库查询语言(6) :Cypher语句-CREATE,MERGR

Cypher图数据库查询语言(7) :Cypher语句-SET,DELETE,REMOVE

Cypher图数据库查询语言(8) :Cypher语句-FOREACH,CREATE UNIQUE

Cypher图数据库查询语言(9) :Cypher语句-RETURN,ORDER BY

Cypher图数据库查询语言(10) :Cypher语句-LIMIT,SKIP

Cypher图数据库查询语言(11) :Cypher语句-WITH,UNWIND,UNION,CALL

语句可分为三类,包括读语句、写语句和通用语句。

  • 读语句:MATCH、OPTIONAL MATCH、WHERE、START、Aggregation和LOAD CSV。
  • 写语句:CREATE、MERGR、SET、DELETE、REMOVE、FOREACH和CREATE UNIQUE。
  • 通用语句:RETURN、ORDER BY、LIMIT、SKIP、WITH、UNWIND、UNION和CALL。

1 MATCH

MATCH 语句用指定的模式检索数据库。

1.1 查找节点

1.1.1 查询所有节点

通过指定一个不带标签的节点的模式,图中的所有节点将返回。

MATCH (n)
RETURN n

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

1.1.2 查询带有某个标签的所有节点

通过指定带有一个标签的节点的模式,可以获取满足该标签的所有节点。

MATCH (movie:Movie)
RETURN movie.title

结果: 返回数据库中的所有电影名。

1.1.3 查询关联节点

符号--意为相关的,这个关系不带有类型和方向。

MATCH (director { name:'Oliver Stone'}) -- (movie)
RETURN movie.titie

结果: 返回'Oliver Stone'导演的所有电影名。

1.1.4 匹配标签

可以为查询的节点增加标签约束。

MATCH (:Person { name:'Oliver Stone'}) -- (movie:Movie)
RETURN movie.titie

结果: 返回与Person 'Oliver Stone'相连的带有Movie标签的所有节点。

1.2 查找关系

1.2.1 外向关系

关系的方向通过 --> 或 <-- 来表示。

MATCH (:Person { name:'Oliver Stone'}) --> (movie)
RETURN movie.titie

结果: 返回与Person 'Oliver Stone'外向连接的所有节点。

1.2.2 有向关系和变量

当需要过滤关系中的属性,或者返回关系的时候,变量就很有必要了。

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

结果: 返回 'Oliver' 的外向关系的类型。

1.2.3 匹配关系类型

当已知要匹配关系的类型时,可通过冒号后面紧跟关系类型。

MATCH (wallstreet:Movie { title:'Wall Street'}) <-[:ACTED_IN]- (actor)
RETURN actor.name

结果: 返回'Wall Street'中的所有演员。

1.2.4 匹配多种关系类型

当需要匹配多种关系中的一种时,可以通过竖线(|)将多个关系连接在一起。

MATCH (wallstreet { title:'Wall Street'}) <-[:ACTED_IN | :DIRECTED]- (person)
RETURN person.name

结果: 返回与'Wall Street'节点关系为ACTED_IN或DIRECTED的所有节点。

1.2.5 匹配关系类型和使用关系变量

如果想通过变量来引用关系和指定关系类型,可以将它们放在一起。例如:

MATCH (wallstreet { title:'Wall Street'}) <- [r:ACTED_IN]- (actor)
RETURN r.role

结果: 返回'Wall Street'中所有演员的角色。

1.3 关系的深度

1.3.1 带有特殊字符的关系类型

某些时候数据库中可能会有非字母字符的类型,或者中间含有空格。可以使用反引号“`”将它们括起来。

下面的例子在 'Charlie Sheen' 和 'Rob Reiber' 之间添加了一个包含空格的关系。

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

查询:

MATCH (n {name:'Rob Reiber'}) - [r:`TYPE WITH SPACE`] -> ()
RETURN type(r)

结果: 返回带有空格的关系类型。

1.3.2 多个关系

关系可以多语句以()--()的形式来表达,或者它们相互连接在一起。例如:

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

结果: 返回 'Charlie Sheen' 演的电影和该电影的导演。

1.3.3 可变长关系

可变长关系和节点的语法如下:

- [:TYPE*minHops..maxHops]->

minHops 和 maxHops 都是可选的,默认值分别为1和无穷大。当没有边界值的时候,点也可以省略。当只设置了一个边界的时候,如果点省略了就意味着是一个固定长度的模式。

MATCH (martin { name:'Charlie Sheen'  }) - [:ACTED_IN*1..3]- (movie:Movie) 
RETURN movie.title

结果: 返回与'Charlie Sheen' 关系为1跳(Hop)到3跳的所有电影。

1.3.4 变长关系的关系变量

当连接两个节点之间的长度是变长的,那么关系变量返回的将可能是一个关系列表。

MATCH (actor { name:'Charlie Sheen'  }) - [r:ACTED_IN*2]- (co_actor) 
RETURN r

结果: 返回一个关系列表。

1.3.5 变长路径上的属性匹配

带有属性的可变长度关系意味着路径上的所有关系都必须包含给定的属性值。在这个查询中,'Charlie Sheen' 和他的父亲'Martin Sheen' 之间有两条路径。其中一条包含一个'blocked'关系,另外一条没有。首先,通过下面语句增加BLOCKKED和UNBLOCKKED关系。

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)

查询:

MATCH p = (charlie:Person) - [* {blocked:FALSE}] - (martin:Person)
WHERE charlie.name = 'Charlie Sheen' AND martin.name = 'Martin Sheen'
RETURN p

**结果:**返回'Charlie Sheen'和'Martin Sheen'之间满足blocked属性值为false的所有关系。

1.3.6 零长路径

如果变长路径的下界值为0,则意味着两个变量指向同一个节点。

MATCH (wallstreet:Movie { title:'Wall Street'}) - [*0..1]- (x)
RETURN x

结果: 返回电影本身及其一跳关系的演员和导演。

1.3.7 命名路径

如果想返回或者需要对路径进行过滤,可以将路径赋值给一个变量。

MATCH p = (michael { name:'Michael Douglas'}) -->()
RETURN p

结果: 返回从开始'Michael Douglas'的两条路径。

1.3.8 匹配一簇关系

当模式包含一簇关系时,关系模式不会指定方向,Cypher将尝试匹配两个方向的关系。

MATCH (a)-[r]-(b)
WHERE id(r) = 0
RETURN a,b

结果: 返回两个相连的节点,一个为开始节点,一个为结束节点。

1.4 最短路径

1.4.1 单条最短路径

通过使用shortestPath函数很容易找到两个节点之间的最短路径,如下所示。

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

上面查询的含义为:找到两个节点之间的最短路径,路径最大长度为15。在搜索最短路径的时候,还可以使用关系类型、最大跳数和方向等约束条件。如果用到了WHERE语句,相关的断言会被包含到shortestPath中去。如果路径的关系元素中用到了none()或者all()断言,那么这些将用于在检索时提高性能。

1.4.2 带断言的最短路径

最短路径模式中WHERE语句的断言通常在检索匹配的最短路径之前就进行处理了。

MATCH (charlie:Person { name:'Charlie Sheen'}),  (mairin:Person { name:'Martin Sheen'}), p =shortestPath((charlie) - [*]-(mairin))
WHERE NONE (r IN rels(p) WHERE type(r) = 'FATHER')
RETURN p

结果: 这个查询寻找'Charlie Sheen'和'Martin Sheen'之间的最短路径,WHERE断言确保不考虑两个节点之间的父亲/儿子关系。

1.4.3 所有最短路径

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

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

结果: 找到了'Martin Sheen'和'Michael Douglas'之间的两条最短路径。

1.5 通过id查询节点或关系

1.5.1 通过id查询节点

可以在断言中使用id()函数来根据id查询节点。

提示:Neo4j会重用已删除的节点和关系的内部id。这意味着依赖Neo4j内部的id存在风险。因此,建议通过程序来产生id。

MATCH (n)
WHERE id(n)=0
RETURN n

结果: 节点id为0的节点将返回。

1.5.2 通过id查询关系

通过id查询关系与节点类似,但在实践中不推荐这么做。

MATCH ()-[r]->()
WHERE id(r)=0
RETURN r

结果: 关系id为0的关系将返回。

1.5.3 通过id查询多个节点

通过id查询多个节点的时候,可以将id放到IN语句中。

MATCH (n)
WHERE id(n) IN [0,3,5]
RETURN n

结果: 这个查询返回了IN语句中列出的所有节点。

2 OPTIONAL MATCH

2.1 简介

OPTIONAL MATCH匹配模式与MATCH类似,不同之处在于,如果没有匹配到,OPTIONAL MATCH将用null作为未匹配到部分的值。

OPTIONAL MATCH在Cypher中类似SQL语句中outer join。

2.2 关系

如果某个关系是可选的,可使用OPTIONAL MATCH。如果关系存在就返回,否则在相应的地方返回null。

MATCH (a:Movie { title:'Wall Street'})
OPTIONAL MATCH (a)-->(x)
RETURN x

结果: 返回了null,因为这个节点没有外向关系。

2.3 可选关系的属性

如果可选的元素为null,那么该元素的属性也返回null。

MATCH (a:Movie { title:'Wall Street'})
OPTIONAL MATCH (a)-->(x)
RETURN x, x.name

结果: 返回了x元素(查询中为null),它的neme属性也为null。

x x.name
<null> <null>

2.4 可选关系类型

可在查询中指定可选关系的类型。

MATCH (a:Movie { title:'Wall Street'})
OPTIONAL MATCH (a)-[r:ACTED_IN]->()
RETURN r

结果: 返回了null关系,因为该节点没有ACTED_IN的外向关系。