reference/docs/neo4j.md
2024-05-09 19:03:58 +08:00

25 KiB
Raw Blame History

Neo4j 备忘清单

这个 neo4j 快速参考备忘单显示了它的常用命令

入门

Neo4J

Neo4j是一个图形数据库由节点通过关系连接在一起。如果您有一个高度相互连接的数据集或者有很多连接的查询您可能会考虑使用图数据库。

运行

$ bin/neo4j start

在 Mac 或者 Linux 中,安装好 JDK 后,直接解压下载好的 Neo4j 包,然后运行上面命令即可。

Neo4J 使用

Neo4J 提供了一个用户友好的 web 界面可以进行各项配置、写入、查询等操作并且提供了可视化功能。类似ElasticSearch 一样,我个人非常喜欢这种开箱即用的设计。

进入管理页面

打开浏览器,输入下面网址,可以进入管理页面

http://127.0.0.1:7474/browser/

图数据库概念

节点 节点通常用于表示数据中的 实体事物。例如,一个 PersonMovie电影
关系 关系用于将两个节点连接在一起,并将数据组织成结构。例如,一个人 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

删除 PersonnameMike节点的 test属性

MATCH (a:Person {name:'Mike'}) SET a.test='test'
MATCH (a:Person {name:'Mike'}) REMOVE a.test

删除 LocationcityPortland 的节点

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);