25 KiB
Neo4j 备忘清单
这个 neo4j 快速参考备忘单显示了它的常用命令
入门
Neo4J
Neo4j是一个图形数据库,由节点通过关系连接在一起。如果您有一个高度相互连接的数据集或者有很多连接的查询,您可能会考虑使用图数据库。
- 下载 Neo4j Desktop 下载 Neo4j 桌面版或服务器版
- Neo4j 沙盒 选择一个数据集 - 无需安装
- Neo4j Aura 在云端获得免费的 Neo4j 实例
- Neo4j 图形学院 免费、自主学习、实践性的在线培训
- GraphGists 使用案例和行业特定的示例图
运行
$ bin/neo4j start
在 Mac 或者 Linux 中,安装好 JDK 后,直接解压下载好的 Neo4j 包,然后运行上面命令即可。
Neo4J 使用
Neo4J 提供了一个用户友好的 web 界面,可以进行各项配置、写入、查询等操作,并且提供了可视化功能。类似ElasticSearch 一样,我个人非常喜欢这种开箱即用的设计。
进入管理页面
打开浏览器,输入下面网址,可以进入管理页面
http://127.0.0.1:7474/browser/
图数据库概念
节点 |
节点通常用于表示数据中的 实体 或 事物。例如,一个 Person(人) 或 Movie(电影)。 |
关系 |
关系用于将两个节点连接在一起,并将数据组织成结构。例如,一个人 acted in(出演) 一部电影。关系有一个 类型 和 方向,尽管在查询时可以忽略方向。 |
标签 |
标签用于将节点分组到不同的类别中。例如,一个人可以有 Person(人) 和 Actor(演员) 标签。 |
关系类型 |
每个关系都有一个类型。关系允许您在图中探索较小的部分。 |
属性 |
节点和关系都可以设置属性。属性是 名称-值对。 |
Neo4j 语法
读取查询结构
[USE] // (使用)
[MATCH WHERE] // (匹配条件)
[OPTIONAL MATCH WHERE] // (可选匹配条件)
// (传递结果并进行排序、跳过或限制)
[WITH [ORDER BY] [SKIP] [LIMIT]]
// (返回结果并进行排序、跳过或限制)
RETURN [ORDER BY] [SKIP] [LIMIT]
仅写入查询结构
[USE] // (使用)
(CREATE | MERGE)* // (创建或合并节点和关系)
// (设置、删除、移除或循环操作)
[SET|DELETE|REMOVE|FOREACH]*
// (返回结果并进行排序、跳过或限制)
[RETURN [ORDER BY] [SKIP] [LIMIT]
读取-写入查询结构
[USE] // (使用)
[MATCH WHERE] // (匹配条件)
[OPTIONAL MATCH WHERE] // (可选匹配条件)
// (传递结果并进行排序、跳过或限制)
[WITH [ORDER BY] [SKIP] [LIMIT]]
(CREATE | MERGE)* // (创建或合并节点和关系)
// (设置、删除、移除或循环操作)
[SET|DELETE|REMOVE|FOREACH]*
// (返回结果并进行排序、跳过或限制)
[RETURN [ORDER BY] [SKIP] [LIMIT]
Neo4j 读取数据
MATCH
MATCH (n:Person)-[:KNOWS]->(m:Person)
WHERE n.name = 'Alice'
节点模式可以包含标签和属性
MATCH (n)-->(m)
在 MATCH 中可以使用任何模式
MATCH (n {name: 'Alice'})-->(m)
带有节点属性的模式
MATCH p = (n)-->(m)
将路径分配给 p
OPTIONAL MATCH (n)-[r]->(m)
可选模式:缺失部分将使用空值
WHERE
WHERE n.property <> $value
使用谓词进行过滤。请注意,WHERE 总是作为 MATCH、OPTIONAL MATCH 或 WITH 子句的一部分。在查询中的其他子句之后放置它将改变它的作用
WHERE EXISTS {
MATCH (n)-->(m) WHERE n.age = m.age
}
使用存在性子查询进行过滤。
RETURN
RETURN *
返回所有变量的值
RETURN n AS columnName
为结果列名使用别名
RETURN DISTINCT n
返回唯一的行
ORDER BY n.property
对结果进行排序
ORDER BY n.property DESC
按降序对结果进行排序
SKIP $skipNumber
跳过一定数量的结果
LIMIT $limitNumber
限制结果的数量
SKIP $skipNumber LIMIT $limitNumber
跳过顶部的结果并限制结果的数量
RETURN count(*)
匹配行的数量。参见聚合函数了解更多
WITH
MATCH (user)-[:FRIEND]-(friend)
WHERE user.name = $name
WITH user, count(friend) AS friends
WHERE friends > 10
RETURN user
WITH 语法类似于 RETURN。它明确地分隔查询部分,允许您声明要传递到下一部分的变量
MATCH (user)-[:FRIEND]-(friend)
WITH user, count(friend) AS friends
ORDER BY friends DESC
SKIP 1
LIMIT 3
RETURN user
ORDER BY、SKIP 和 LIMIT 也可以与 WITH 一起使用
UNION
MATCH (a)-[:KNOWS]->(b)
RETURN b.name
UNION
MATCH (a)-[:LOVES]->(b)
RETURN b.name
返回所有查询结果的唯一并集。结果列的类型和名称必须匹配
MATCH (a)-[:KNOWS]->(b)
RETURN b.name
UNION ALL
MATCH (a)-[:LOVES]->(b)
RETURN b.name
返回所有查询结果的并集,包括重复行
Neo4j 写入数据
CREATE
CREATE (n {name: $value})
创建具有指定属性的节点
CREATE (n $map)
创建具有指定属性的节点
UNWIND $listOfMaps AS properties
CREATE (n) SET n = properties
创建具有指定属性的节点
CREATE (n)-[r:KNOWS]->(m)
创建具有指定类型和方向的关系;将变量绑定到它
CREATE (n)-[:LOVES {since: $value}]->(m)
创建具有指定类型、方向和属性的关系
SET
SET n.property1 = $value1,
n.property2 = $value2
更新或创建属性
SET n = $map
设置所有属性。这将删除任何现有属性
SET n += $map
添加和更新属性,同时保留现有属性
SET n:Person
向节点添加一个标签 Person
MERGE
MERGE (n:Person {name: $value})
ON CREATE SET n.created = timestamp()
ON MATCH SET
n.counter = coalesce(n.counter, 0) + 1,
n.accessTime = timestamp()
匹配模式或在不存在时创建它。使用 ON CREATE 和 ON MATCH 进行条件更新
MATCH (a:Person {name: $value1}),
(b:Person {name: $value2})
MERGE (a)-[r:LOVES]->(b)
MERGE 查找或创建节点之间的关系
MATCH (a:Person {name: $value1})
MERGE
(a)-[r:KNOWS]->(b:Person {name: $value3})
MERGE 查找或创建与节点关联的路径
DELETE
DELETE n, r
删除一个节点和一个关系
DETACH DELETE n
删除一个节点以及与其连接的所有关系
MATCH (n)
DETACH DELETE n
从数据库中删除所有节点和关系
REMOVE
REMOVE n:Person
从 n 中移除一个标签
REMOVE n.property
移除一个属性
FOREACH
FOREACH (r IN relationships(path) |
SET r.marked = true)
对路径中的每个关系执行一个变异操作。
FOREACH (value IN coll |
CREATE (:Person {name: value}))
对列表中的每个元素执行一个变异操作。
调用子查询
CALL {
MATCH (p:Person)-[:FRIEND_OF]->(other:Person) RETURN p, other
UNION
MATCH (p:Child)-[:CHILD_OF]->(other:Parent) RETURN p, other
}
这调用了一个具有两个联合部分的子查询。子查询的结果之后可以进行后处理。
调用存储过程
CALL db.labels() YIELD label
这显示了对内置过程 db.labels 的独立调用,以列出数据库中使用的所有标签。请注意,所需的过程参数在过程名称后的括号中明确给出。
CALL db.labels() YIELD *
独立调用可以使用 YIELD * 返回所有列。
CALL java.stored.procedureWithArgs
独立调用可以省略 YIELD,并且也可以通过语句参数隐式提供参数,例如,一个需要一个参数输入的独立调用可以通过传递参数映射 {input: 'foo'} 来运行。
CALL db.labels() YIELD label
RETURN count(label) AS count
在更大的查询中调用内置过程 db.labels 来计算数据库中使用的所有标签。在更大的查询中进行调用时,总是需要显式传递参数和使用 YIELD 明确命名结果。
导入
LOAD CSV FROM
'https://neo4j.com/docs/cypher-refcard/4.3/csv/artists.csv' AS line
CREATE (:Artist {name: line[1], year: toInteger(line[2])})
从 CSV 文件加载数据并创建节点。
LOAD CSV WITH HEADERS FROM
'https://neo4j.com/docs/cypher-refcard/4.3/csv/artists-with-headers.csv' AS line
CREATE (:Artist {name: line.Name, year: toInteger(line.Year)})
加载包含标题的 CSV 数据。
USING PERIODIC COMMIT 500
LOAD CSV WITH HEADERS FROM
'https://neo4j.com/docs/cypher-refcard/4.3/csv/artists-with-headers.csv' AS line
CREATE (:Artist {name: line.Name, year: toInteger(line.Year)})
在导入大量数据时,每处理500行后提交当前事务。
LOAD CSV FROM
'https://neo4j.com/docs/cypher-refcard/4.3/csv/artists-fieldterminator.csv'
AS line FIELDTERMINATOR ';'
CREATE (:Artist {name: line[1], year: toInteger(line[2])})
使用不同的字段分隔符,而不是默认的逗号(周围没有空白)。
LOAD CSV FROM
'https://neo4j.com/docs/cypher-refcard/4.3/csv/artists.csv' AS line
RETURN DISTINCT file()
返回 LOAD CSV 处理的文件的绝对路径,如果在 LOAD CSV 上下文之外调用则返回 null。
LOAD CSV FROM
'https://neo4j.com/docs/cypher-refcard/4.3/csv/artists.csv' AS line
RETURN linenumber()
返回 LOAD CSV 当前正在处理的行号,如果在 LOAD CSV 上下文之外调用则返回 null。
运算符
通用 | DISTINCT, ., [] |
数学 | +, -, *, /, %, ^ |
比较 | =, <>, <, >, <=, >=, IS NULL, IS NOT NULL |
布尔 | AND, OR, XOR, NOT |
字符串 | + |
列表 | +, IN, [x], [x .. y] |
正则表达式 | =~ |
字符串匹配 | STARTS WITH, ENDS WITH, CONTAINS |
null
null
用于表示缺失/未定义的值。null
不等于null
。不知道两个值是否相等并不意味着它们是相同的值。因此,表达式null = null
得到的是null
而不是true
。要检查表达式是否为null
,请使用IS NULL
。- 算术表达式、比较和函数调用(除了
coalesce
)将返回null
如果任何参数为null
。 - 尝试访问列表中缺失的元素或不存在的属性将得到
null
。 - 在
OPTIONAL MATCH
子句中,缺失部分的模式将使用null
。
Patterns
(n:Person)
具有 Person 标签的节点
(n:Person:Swedish)
具有 Person 和 Swedish 标签的节点
(n:Person {name: $value})
具有声明的属性的节点
()-[r {name: $value}]-()
匹配具有声明的属性的关系
(n)-->(m)
从 n 到 m 的关系
(n)--(m)
在 n 和 m 之间的任意方向上的关系
(n:Person)-->(m)
带有指向 m 的关系的标记为 Person 的节点
(m)<-[:KNOWS]-(n)
从 n 到 m 的类型为 KNOWS 的关系
(n)-[:KNOWS|:LOVES]->(m)
从 n 到 m 的类型为 KNOWS 或类型为 LOVES 的关系
(n)-[r]->(m)
将关系绑定到变量 r
(n)-[*1..5]->(m)
从 n 到 m 之间的 1 到 5 个关系的变长路径
(n)-[*]->(m)
从 n 到 m 之间的任意数量的关系的变长路径。(请参阅性能部分)
(n)-[:KNOWS]->(m {property: $value})
从节点 n 到节点 m,类型为 KNOWS 的关系,具有声明的属性
shortestPath((n1:Person)-[*..6]-(n2:Person))
查找单一最短路径
allShortestPaths((n1:Person)-[*..6]->(n2:Person))
查找所有最短路径
size((n)-->()-->())
计算与模式匹配的路径数量
USE
USE myDatabase
选择 myDatabase 来执行查询,或针对其执行查询的部分
USE neo4j
MATCH (n:Person)-[:KNOWS]->(m:Person)
WHERE n.name = 'Alice'
针对 Neo4j 数据库执行的 MATCH 查询
SHOW FUNCTIONS 和 PROCEDURES
SHOW FUNCTIONS
列出所有可用函数
SHOW PROCEDURES EXECUTABLE YIELD name
列出当前用户可以执行的所有过程,并仅返回过程的名称
标签
CREATE (n:Person {name: $value})
创建一个带有标签和属性的节点
MERGE (n:Person {name: $value})
匹配或创建具有该标签和属性的唯一节点
SET n:Spouse:Parent:Employee
向节点添加标签
MATCH (n:Person)
匹配标记为“Person”的节点
MATCH (n:Person)
WHERE n.name = $value
匹配具有给定名称的标记为“Person”的节点
WHERE (n:Person)
检查节点上标签的存在
labels(n)
节点的标签
REMOVE n:Person
从节点中移除标签
Lists
['a', 'b', 'c'] AS list
文字列表用方括号声明
size($list) AS len, $list[0] AS value
列表可以作为参数传递
range($firstNum, $lastNum, $step) AS list
range() 创建一个数字列表(step是可选的),其他返回列表的函数有:labels()、nodes()、relationships()
MATCH p = (a)-[:KNOWS*]->()
RETURN relationships(p) AS r
可以使用命名路径和 relationships() 返回变长路径的关系列表
RETURN matchedNode.list[0] AS value,
size(matchedNode.list) AS len
属性可以是字符串、数字或布尔值的列表。
list[$idx] AS value,
list[$startIdx..$endIdx] AS slice
可以使用方括号中的 idx 下标来访问列表元素。无效的索引返回 null。可以使用起始索引到结束索引的间隔来检索片段,每个索引都可以省略或为负数。超出范围的元素将被忽略
UNWIND $names AS name
MATCH (n {name: name})
RETURN avg(n.age)
使用 UNWIND,任何列表都可以转换回单独的行。该示例匹配一个名字列表中的所有名字
MATCH (a)
RETURN [(a)-->(b) WHERE b.name = 'Bob' | b.age]
可以使用模式推导直接从匹配中进行自定义投影
MATCH (person)
RETURN person { .name, .age}
映射投影可以很容易地从节点、关系和其他映射值构造出来
Maps
{name: 'Alice', age: 38, address: {
city: 'London',residential: true}}
文字映射使用大括号声明,就像属性映射一样。支持列表
WITH {person: {name: 'Anne', age: 25}} AS p
RETURN p.person.name
访问嵌套映射的属性
MERGE (p:Person {name: $map.name})
ON CREATE SET p = $map
映射可以作为参数传递,并且可以作为映射或通过访问键来使用
MATCH (matchedNode:Person)
RETURN matchedNode
节点和关系被返回为它们数据的映射
map.name, map.age, map.children[0]
可以通过它们的键访问映射条目。无效的键会导致错误
CASE
CASE n.eyes
WHEN 'blue' THEN 1
WHEN 'brown' THEN 2
ELSE 3
END
从匹配的 WHEN 值返回 THEN 值。ELSE 值是可选的,如果缺失,则替换为 null
CASE
WHEN n.eyes = 'blue' THEN 1
WHEN n.age < 40 THEN 2
ELSE 3
END
从第一个评估为 true 的 WHEN 谓词返回 THEN 值。谓词按顺序进行评估
Predicates 谓词
n.property <> $value
使用比较运算符
toString(n.property) = $value
使用函数
n.number >= 1 AND n.number <= 10
使用布尔运算符来组合谓词
1 <= n.number <= 10
使用链接运算符来组合谓词
n:Person
检查节点标签
variable IS NOT NULL
检查某物是否不为 null,例如某个属性是否存在
n.property IS NULL OR n.property = $value
要么属性不存在,要么谓词为 true
n.property = $value
不存在的属性返回 null,它与任何值都不相等
n["property"] = $value
也可以使用动态计算的属性名称来访问属性
n.property STARTS WITH 'Tim' OR
n.property ENDS WITH 'n' OR
n.property CONTAINS 'goodie'
字符串匹配
n.property =~ 'Tim.*'
字符串正则表达式匹配
(n)-[:KNOWS]->(m)
确保模式至少有一个匹配项
NOT (n)-[:KNOWS]->(m)
从结果中排除对 (n)-[:KNOWS]->(m) 的匹配
n.property IN [$value1, $value2]
检查一个元素是否存在于列表中
列表谓词
all(x IN coll WHERE x.property IS NOT NULL)
如果列表中所有元素都满足谓词,则返回 true。
any(x IN coll WHERE x.property IS NOT NULL)
如果列表中至少有一个元素满足谓词,则返回 true。
none(x IN coll WHERE x.property IS NOT NULL)
如果列表中所有元素都不满足谓词,则返回 true。
single(x IN coll WHERE x.property IS NOT NULL)
如果列表中恰好有一个元素满足谓词,则返回 true。
列表表达式
size($list)
列表中的元素数量
reverse($list)
反转列表中元素的顺序
head($list), last($list), tail($list)
head() 返回列表的第一个元素,last() 返回列表的最后一个元素。tail() 返回除第一个元素外的所有元素。对于空列表,所有函数返回 null
[x IN list | x.prop]
对原始列表中每个元素的表达式值组成的列表
[x IN list WHERE x.prop <> $value]
过滤出谓词为 true 的元素组成的列表
[x IN list WHERE x.prop <> $value | x.prop]
对列表进行过滤,并从每个符合条件的元素中提取表达式的值
reduce(s = "", x IN list | s + x.prop)
对列表中的每个元素求值,并累积结果
函数
coalesce(n.property, $defaultValue)
返回第一个非空表达式
timestamp()
自1970年1月1日UTC午夜以来的毫秒数
id(nodeOrRelationship)
关系或节点的内部ID
toInteger($expr)
将给定的输入转换为整数(如果可能),否则返回 null
toFloat($expr)
将给定的输入转换为浮点数(如果可能),否则返回 null
toBoolean($expr)
将给定的输入转换为布尔值(如果可能),否则返回 null
keys($expr)
返回节点、关系或映射的属性名称的字符串表示形式列表
properties($expr)
返回包含节点或关系的所有属性的映射
路径函数
length(path)
路径中的关系数量。
nodes(path)
路径中的节点列表。
relationships(path)
路径中的关系列表。
[x IN nodes(path) | x.prop]
从路径中的节点中提取属性。
空间函数
point({x: $x, y: $y})
返回一个二维笛卡尔坐标系中的点。
point({latitude: $y, longitude: $x})
返回一个二维地理坐标系中的点,坐标以十进制度数指定。
point({x: $x, y: $y, z: $z})
返回一个三维笛卡尔坐标系中的点。
point({latitude: $y, longitude: $x, height: $z})
返回一个三维地理坐标系中的点,纬度和经度以十进制度数表示,高度以米为单位。
distance(point({x: $x1, y: $y1}), point({x: $x2, y: $y2}))
返回一个浮点数,表示两点之间的线性距离。返回的单位将与点坐标的单位相同,它适用于二维和三维笛卡尔点。
distance(point({latitude: $y1, longitude: $x1}), point({latitude: $y2, longitude: $x2}))
返回两点之间的大地距离,单位为米。它也可以用于三维地理点。
Neo4j 示例
创建
创建多个节点
CREATE (n:Person {name:'Sally'}) RETURN n;
CREATE (n:Person {name:'Steve'}) RETURN n;
创建 FRIENDS
关系
MATCH (a:Person {name:'Sally'}),
(b:Person {name:'Steve'})
MERGE (a)-[:FRIENDS]->(b)
创建节点的时候就建好 FRIENDS
关系
CREATE (a:Person {name:'Todd'})-[r:FRIENDS]->(b:Person {name:'Carlos'})
为创建完成的关系增加 since
属性
MATCH (a:Person {name:'Sally'}),
(b:Person {name:'Steve'})
MERGE (a)-[:FRIENDS {since:2001}]->(b)
删除
删除所有节点
MATCH (n) DETACH DELETE n
删除 Person
中 name
为 Mike
节点的 test
属性
MATCH (a:Person {name:'Mike'}) SET a.test='test'
MATCH (a:Person {name:'Mike'}) REMOVE a.test
删除 Location
中 city
为 Portland
的节点
MATCH (a:Location {city:'Portland'}) DELETE a
删除有关系的节点(此处rel是写死的,指的是所有关系)
MATCH (a:Person {name:'Todd'})-[rel]-(b:Person) DELETE a,b,rel
查询
查询所有在 Boston
出生的人物
MATCH (a:Person)-[:BORN_IN]->(b:Location {city:'Boston'}) RETURN a,b
查询所有对外有关系的节点
MATCH (a)-->() RETURN a
查询所有有关系的节点
MATCH (a)--() RETURN a
查询所有对外有关系的节点,以及关系类型
MATCH (a)-[r]->() RETURN a.name, type(r)
查询所有有结婚关系的节点
MATCH (n)-[:MARRIED]-() RETURN n
查找某人的朋友的朋友
MATCH (a:Person {name:'Mike'})-[r1:FRIENDS]-()-[r2:FRIENDS]-(friend_of_a_friend) RETURN friend_of_a_friend.name AS fofName
创建节点和关系
// 创建节点
CREATE (n:Person {name: 'Alice', age: 30})
CREATE (n:Person {name: 'Bob', age: 25})
// 创建关系
MATCH (alice:Person {name: 'Alice'}), (bob:Person {name: 'Bob'})
CREATE (alice)-[:FRIENDS]->(bob)
增加/修改节点的属性
MATCH (a:Person {name:'Liz'}) SET a.age=34
MATCH (a:Person {name:'Shaw'}) SET a.age=32
MATCH (a:Person {name:'John'}) SET a.age=44
MATCH (a:Person {name:'Mike'}) SET a.age=25
查询节点和关系
// 查询所有节点和关系
MATCH (n)
RETURN n
// 查询特定节点
MATCH (n:Person)
WHERE n.name = 'Alice'
RETURN n
// 查询节点的关系
MATCH (n:Person)-[r]->()
WHERE n.name = 'Alice'
RETURN r
更新节点和关系
// 更新节点属性
MATCH (n:Person {name: 'Alice'})
SET n.age = 31
RETURN n
// 删除节点
MATCH (n:Person {name: 'Bob'})
DELETE n
更复杂的查询
// 查找 Alice 的朋友的朋友
MATCH (alice:Person {name: 'Alice'})-[:FRIENDS]->()-[:FRIENDS]->(fof)
RETURN fof
// 查找共同朋友,这里的“,”相当于 AND 条件
MATCH (alice:Person {name: 'Alice'})-[:FRIENDS]->(friend),
(bob:Person {name: 'Bob'})-[:FRIENDS]->(friend)
RETURN friend
通过观察John的朋友
看过的电影为John
推荐电影,并且不再推荐John
他自己已经看过的电影。
MATCH (tom:Person {name: "John Johnson"})-[:IS_FRIEND_OF]->(user)-[:HAS_SEEN]->(movie)
WHERE NOT tom-[:HAS_SEEN]->(movie) RETURN movie.name;
找出所有标题以Apollo
开头且发行年份早于1996
年的电影节点
MATCH (node:Movie)
WHERE node.title =~ 'Apollo.*' AND node.released < 1996
RETURN node
排序&分页
以电影名字排序,每一网页只显示10部电影,下面的查询返回了第三页(21~30项)。
match (alice:Person {name: 'Alice'})-[HAS_SEEN]->(movie)
return movie
order by movie.name
skip 20
limit 10
聚合函数
计算每一部电影被观看的数量,按数量排序
match (node:Movie)-[:HAS_BEEN_SEEN]->()
return node,count(*)
order by count(*) desc;
要求John
所有朋友的平均年龄,可以使用以下查询
match (node:users{name: "John Johnson"})-[:IS_FRIEND_OF]-(friend)
where HAS(friend.yearOfBirth)
return avg(2014-friend.yearOfBirth);