当前位置:   article > 正文

Neo4j使用记录--基础篇(Cypher)【语法】_neo4j cypher语法

neo4j cypher语法

引言

日常我们在创建知识图谱的时候,入门的图数据库几乎为Neo4j数据库,Cypher 是图形数据库 Neo4j 的查询语言。我们要掌握Neo4j数据库,必须掌握Cypher语言。以下是我个人学习中的记录,恭请指教!!

Cypher–简介

Cypher 受到不同方法的启发,如 WHERE ORDER BY 受到了 SQL 的启发,模式匹配则借用了 SPARQL 的表达式方法,一些列表语义借用了 Haskell 和 Python 等语言,正则表达式匹配实现实用Scala programming language语言。

  1. Cypher 的构造基于英文散文和简洁的图像,基于英语单词和灵巧的图解,使查询易于编写和阅读。
  2. Cypher是一个描述性的图形查询语言,允许不必编写图形结构的遍历代码对图形存储有表现力和效率的查询。
  3. Cypher设计的目的是一个人类查询语言,适合于开发者和在数据库上做点对点模式(ad-hoc)查询的专业操作人员。
  4. Cypher是一个申明式的语言。对比命令式语言如Java和脚本语言如Gremlin和JRuby,它的焦点在于从图中如何找回(what to retrieve),而不是怎么去做。这使得在不对用户公布的实现细节里关心的是怎么优化查询。

Cypher–能力

Cypher具备的能力:

  • Cypher通过模式匹配图数据库中的节点和关系,来提取信息或者修改数据。
  • Cypher语句中允许使用变量,用来表示命名、绑定元素和参数。
  • Cypher语句可以对节点、关系、标签和属性进行创建、更新和删除操作。
  • Cypher语句可以管理索引和约束。

Cypher–语法

  1. 节点语法:采用一对圆括号来表示节点。如:()、(foo)
  2. 关系语法:使用一对短横线表示无方向关系,有方向加箭头。如:-[role]-、-[:ACTED_IN]->、-[role:ACTED_IN]->
  3. 模式语法:将节点和关系的语法组合在一起可以表达模式。如:(keanu: Person: Actor {name: “Keanu Rteves”}-[role:ACTED_IN {roles: [“Neo”]}]->{matrix: Movie {title: “The Matrix”}})

Cypher–数值类型

数值、字符串、布尔、节点、关系、路径、映射(Map)、列表(List)

Cypher–函数:

断言(Predicate)函数、标量(Scalar)函数、列表(List)函数、数学(Math)函数、字符串(String)函数、自定义函数

函数函数函数
标量(Scalar)函数列表(List)函数数学(Math)函数
字符串(String)函数断言(Predicate)函数自定义函数

查询语法

筛选查询

查看数据Schema表结构

CALL db.schema.visualization()
  • 1

查看节点属性类型

CALL db.schema.nodeTypeProperties()
  • 1
CALL apoc.meta.nodeTypeProperties()
  • 1

查看关系属性类型

CALL db.schema.relTypeProperties()
  • 1

查看关系图中的唯一性约束索引

SHOW CONSTRAINTS
  • 1

基本查询

基本语法

查询另一端节点标签
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)<-[:DIRECTED]-(p)
WHERE  p.born.year > 1960
RETURN p.name, p.born, labels(p), m.title
  • 1
  • 2
  • 3
查询关系类型
MATCH (p:Person)-[r]->(m:Movie)
WHERE  p.name = 'Tom Hanks'
RETURN m.title AS movie, type(r) AS relationshipType
  • 1
  • 2
  • 3
查询是否在列表属性中
MATCH (m:Movie)
WHERE "Israel" IN m.countries
RETURN m.title, m.languages, m.countries
  • 1
  • 2
  • 3
查询属性是否存在

IS NULL IS NOT NULL

MATCH (p:Person)
WHERE p.died IS NULL
AND p.born.year <= 1922
RETURN p.name, p.born, p.died
  • 1
  • 2
  • 3
  • 4
大小写开头
统一大小写 都大写、以什么开头
MATCH (m:Movie)
WHERE toUpper(m.title) STARTS WITH 'LIFE IS'
RETURN m.title
  • 1
  • 2
  • 3
统一大小写 都小写、包含谓词
MATCH (p:Person)-[r]->(m:Movie)
WHERE toLower(r.role) CONTAINS "dog"
RETURN p.name, r.role, m.title
  • 1
  • 2
  • 3
判断是否存在
是否存在,存在,返回改行exists
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WHERE  p.name = 'Tom Hanks'
AND exists {(p)-[:DIRECTED]->(m)}
RETURN p.name, labels(p), m.title
  • 1
  • 2
  • 3
  • 4

返回结果的查询操作

使用关键字查询模式和性能分析

PROFILE

关键字显示从查询中的图形中检索到的总行数

PROFILE MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WHERE  p.name = 'Tom Hanks'
AND exists {(p)-[:DIRECTED]->(m)}
RETURN m.title
  • 1
  • 2
  • 3
  • 4
OPTIONAL MATCH

将模式与图形匹配,就像这样。不同之处在于,如果未找到匹配项,则将使用 null 来表示模式的缺失部分。

MATCH (m:Movie) WHERE m.title = "Kiss Me Deadly"
MATCH (m)-[:IN_GENRE]->(g:Genre)<-[:IN_GENRE]-(rec:Movie)
OPTIONAL MATCH (m)<-[:ACTED_IN]-(a:Actor)-[:ACTED_IN]->(rec)
RETURN rec.title, a.name
  • 1
  • 2
  • 3
  • 4
ORDER BY

返回的结果排序 降序 ORDER BY ... DESC 默认升序 ORDER BY ... ASC

MATCH (m:Movie)<-[ACTED_IN]-(p:Person)
WHERE m.imdbRating IS NOT NULL
RETURN m.title, m.imdbRating, p.name, p.born
ORDER BY m.imdbRating DESC, p.born DESC
  • 1
  • 2
  • 3
  • 4
SKIP LIMIT

返回结果跳过或者限制数量

MATCH (p:Person)
WHERE p.born.year = 1980
RETURN  p.name as name,
p.born AS birthDate
ORDER BY p.born SKIP 40 LIMIT 10
  • 1
  • 2
  • 3
  • 4
  • 5
DISTINCT

返回结果 去重

MATCH (p:Person)-[:DIRECTED | ACTED_IN]->(m:Movie)
WHERE p.name = 'Tom Hanks'
RETURN DISTINCT m.title, m.released
ORDER BY m.title
  • 1
  • 2
  • 3
  • 4
{.··, .··}

返回数据以节点的JSON样式

MATCH (p:Person)
WHERE p.name CONTAINS "Thomas"
RETURN p { .* } AS person
ORDER BY p.name ASC
// 自定义在对象中返回的属性
MATCH (p:Person)
WHERE p.name CONTAINS "Thomas"
RETURN p { .name, .born } AS person
ORDER BY p.name
// 向返回的对象数据添加信息 如例:加favorite属性
MATCH (m:Movie)<-[:DIRECTED]-(d:Director)
WHERE d.name = 'Woody Allen'
RETURN m {.*, favorite: true} AS movie
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
结果数据运算

返回的数据进行运算

MATCH (m:Movie)<-[:ACTED_IN]-(p:Person)
WHERE m.title CONTAINS 'Toy Story' AND
p.died IS NULL
RETURN 'Movie: ' + m.title AS movie,
p.name AS actor,
p.born AS dob,
date().year - p.born.year AS ageThisYear
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
CASE ... END

返回的结果进行条件更改

// 转换返回的数据以反映电影的时间范围
MATCH (m:Movie)<-[:ACTED_IN]-(p:Person)
WHERE p.name = 'Henry Fonda'
RETURN m.title AS movie,
CASE
WHEN m.year < 1940 THEN 'oldies'
WHEN 1940 <= m.year < 1950 THEN 'forties'
WHEN 1950 <= m.year < 1960 THEN 'fifties'
WHEN 1960 <= m.year < 1970 THEN 'sixties'
WHEN 1970 <= m.year < 1980 THEN 'seventies'
WHEN 1980 <= m.year < 1990 THEN 'eighties'
WHEN 1990 <= m.year < 2000 THEN 'nineties'
ELSE  'two-thousands'
END
AS timeFrame
// 第二个例子
MATCH (m:Movie)<-[:ACTED_IN]-(p:Person)
WHERE m.title CONTAINS 'Toy Story'
RETURN m.title AS movie,
p.name AS actor,
p.born AS dob,
CASE 
WHEN p.died IS NULL THEN date().year - p.born.year WHEN p.died IS NOT NULL THEN "Died" END
AS ageThisYear
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

节点数据操作

聚合
公式含义
MAX()最大值
min()最小值
avg()均值
stddev()标准差
sum()求和
统计
MATCH (a:Person)-[:ACTED_IN]->(m:Movie)<-[:DIRECTED]-(d:Person)
RETURN a.name, d.name,
count(*) AS numMovies
ORDER BY numMovies DESC
  • 1
  • 2
  • 3
  • 4
返回列表
MATCH (p:Person)
RETURN p.name, [p.born, p.died] AS lifeTime
LIMIT 10
  • 1
  • 2
  • 3
返回结果创建列表

collect 将值聚合到列表中。该值可以是任何表达式,例如属性值、节点或函数或操作的结果

MATCH (a:Person)-[:ACTED_IN]->(m:Movie)
RETURN a.name AS actor,
count(*) AS total,
collect(m.title) AS movies
ORDER BY total DESC LIMIT 10
  • 1
  • 2
  • 3
  • 4
  • 5
消除列表中的重复值
MATCH (a:Person)-[:ACTED_IN]->(m:Movie)
WHERE m.year = 1920
RETURN  collect( DISTINCT m.title) AS movies,
collect( a.name) AS actors
  • 1
  • 2
  • 3
  • 4
访问列表元素 head() tail
// 返回列表中元素的第一个值
MATCH (a:Person)-[:ACTED_IN]->(m:Movie)
RETURN m.title AS movie,
collect(a.name)[0] AS castMember,
size(collect(a.name)) as castSize
// 从第二个返回列表元素
MATCH (a:Person)-[:ACTED_IN]->(m:Movie)
RETURN m.title AS movie,
collect(a.name)[2..] AS castMember,
size(collect(a.name)) as castSize
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
统计返回列表值得数据 size()
//Query 1  profile 测试查询性能
PROFILE MATCH (g:Genre)<-[:IN_GENRE]-(m)
RETURN g.name AS genre,
size(collect(m)) AS numMovies
ORDER BY size(collect(m)) DESC
  • 1
  • 2
  • 3
  • 4
  • 5
结果进行列表查询
MATCH (m:Movie)
RETURN m.title as movie,
[x IN m.countries WHERE x = 'USA' OR x = 'Germany']
AS country LIMIT 500
  • 1
  • 2
  • 3
  • 4
模式列表查询

指定带有方括号的列表,以包含图案后跟管道字符,然后指定将在模式列表中放置的值。

MATCH (m:Movie)
WHERE m.year = 2015
RETURN m.title,
[(dir:Person)-[:DIRECTED]->(m) | dir.name] AS directors,
[(actor:Person)-[:ACTED_IN]->(m) | actor.name] AS actors
  • 1
  • 2
  • 3
  • 4
  • 5
模式理解的另一个实例
// 电影的标题与电影年份连接,作为要添加的值作为返回的列表的元素。
MATCH (a:Person {name: 'Tom Hanks'})
RETURN 
[(a)-->(b:Movie) WHERE b.title CONTAINS "Toy" | b.title + ": " + b.year] AS movies
  • 1
  • 2
  • 3
  • 4

日期查询

确定两个日期时间值之间的差异

// 返回一个持续时间值,该值表示两个值之间的天数和月数以及时间
MATCH (x:Test {id: 1})
RETURN duration.between(x.date1,x.date2)
                        
// 返回两个日期时间值之间的持续时间(以天为单位)
MATCH (x:Test {id: 1})
RETURN duration.inDays(x.datetime1,x.datetime2).days
                       
// 添加6个月的持续时间
MATCH (x:Test {id: 1})
RETURN x.date1 + duration({months: 6})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

使用APOC设置日期和时间格式

MATCH (x:Test {id: 1})
RETURN x.datetime as Datetime,
apoc.temporal.format( x.datetime, 'HH:mm:ss.SSSS')
AS formattedDateTime

// 结果
"2022-08-22T08:13:37.150000000Z"
"08:13:37.1500"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

APOC转换为另一日期格式

MATCH (x:Test {id: 1})
RETURN apoc.date.toISO8601(x.datetime.epochMillis, "ms")
AS iso8601
  • 1
  • 2
  • 3

使用格式字符串分析任意格式化时态值。apoc.temporal.toZonedTemporal()

图形遍历–查询性能

图形遍历,最重要的是:让查询更具性能优化

查询锚点(可理解为节点)

单个锚点

锚点通常由存储在图形中的元数据或内联或子句中提供的筛选器确定。

查询的定位点将基于需要检索到内存中的最少节点数。

多个锚点

默认情况下,一组锚点节点由与查询路径和用于筛选查询的子句相关的元数据确定。在某些情况下,您可能有多个锚点节点集

PROFILE
MATCH (p1:Person)-[:ACTED_IN]->(m1)
MATCH (m2)<-[:ACTED_IN]-(p2:Person)
WHERE p1.name = 'Tom Hanks'
AND p2.name = 'Meg Ryan'
AND m1 = m2
RETURN m1.title

// 在此查询中,将检索所有 p1 节点以及所有 p2 节点。此查询有两组锚点节点。它在应用相等性筛选器之前检索锚点节点。查询计划程序会尝试尽早应用筛选器以减少基数(行数)。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

路径展开

作为定位点集一部分的已加载的初始节点具有指向关系的指针,这些关系指向关系另一端的节点。

在查询时添加路径,可加快查询效率

基本查询遍历–深度优先

相同查询下,第一种查询比第二种查询更快

多模式查询遍历
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WHERE p.name = 'Eminem'
RETURN  m.title AS movies
  • 1
  • 2
  • 3

查询性能以及过程演示

穿越埃米纳姆的联合演员

多子句查询遍历
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WHERE p.name = 'Eminem'
MATCH (allActors:Person)-[:ACTED_IN]->(m)
RETURN m.title AS movie, collect(allActors.name) AS allActors
  • 1
  • 2
  • 3
  • 4

查询性能以及过程演示

使用多个 Match 子句进行遍历

避免使用过多标签

图形优化

减少查询模式中使用的标签

PROFILE MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WHERE p.name = 'Tom Hanks'
RETURN m.title AS movie
  • 1
  • 2
  • 3

更高性能方法

PROFILE MATCH (p:Person)-[:ACTED_IN]->(m)
WHERE p.name = 'Tom Hanks'
RETURN m.title AS movie
  • 1
  • 2
  • 3

路径查询更具优化

以下两种返回结果一致,但在性能和优化上第二种更优

MATCH (person:Person)-[]->(movie)
WHERE person.name = 'Walt Disney'
RETURN person, movie
  • 1
  • 2
  • 3
MATCH p = ((person:Person)-[]->(movie))
WHERE person.name = 'Walt Disney'
RETURN p
  • 1
  • 2
  • 3
路径有用的函数:
  • length(p)返回路径的长度。
  • nodes(p)返回包含路径节点的列表。
  • relationships(p)返回一个列表,其中包含路径的关系。

图形遍历–长度遍历(路径)

在Neo4j中,始终坚持关系的独特性。也就是说,两个节点之间永远不会有两个相同类型和方向的关系。这使得Neo4j能够避免图形遍历中的循环或无限循环。

最短路径

// 没有限制关系
MATCH p = shortestPath((p1:Person)-[*]-(p2:Person))
WHERE p1.name = "Eminem"
AND p2.name = "Charlton Heston"
RETURN  p

//关系类型限制为特定关系
MATCH p = shortestPath((p1:Person)-[:ACTED_IN*]-(p2:Person))
WHERE p1.name = "Eminem"
AND p2.name = "Charlton Heston"
RETURN  p
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

变长遍历

两个跃点(两条关系)
MATCH (p:Person {name: 'Eminem'})-[:ACTED_IN*2]-(others:Person)
RETURN  others.name

// 检索埃米纳姆人节点。
// 然后,两个ACTED_IN关系通过“电影”节点遍历 8 英里,以返回三个“人”节点。
// 然后,两个ACTED_IN关系通过Hip Hop Witch,Da的电影节点遍历,以返回三个Person节点。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

距离埃米纳姆2英里的人

四个跃点(四条关系)
MATCH (p:Person {name: 'Eminem'})-[:ACTED_IN*4]-(others:Person)
RETURN  others.name
                                                 
// 检索埃米纳姆人节点。
// 然后,通过 Movie 节点遍历ACTED_IN关系,在该节点中检索 8 英里的布列塔尼·墨菲和 Little Black Book 以返回两个 Person 节点。
// 然后,四个ACTED_IN关系通过“8英里”和“预言II”的电影节点遍历,以返回两个“人”节点。
// 仅返回正好来自 Eminem 的 4 个跃点的人员节点。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

距离埃米纳姆4英里的人

查询最多四跳距离

这种深度优先的遍历和检索将一直持续到检索到两个跃点和四个跃点之外的所有 Person 节点为止。

MATCH (p:Person {name: 'Eminem'})-[:ACTED_IN*1..4]-(others:Person)
RETURN  others.name
                                                   
// 检索埃米纳姆人节点。
// 然后,ACTED_IN关系通过“电影”节点遍历 8 英里和“小黑皮书”。
// 在此遍历期间,我们检索两个跃点外的 Person 节点和四个跃点外的两个 Person 节点。
// 然后,通过电影节点遍历 8 英里和预言 II 的ACTED_IN关系。
// 我们已经检索到了四个跳跃之外的布列塔尼·墨菲,但我们又添加了两个Person 节点。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

距离埃米纳姆4英里的人

流水线查询

with子句定义作用域变量

使用子句定义和初始化要在查询中使用的变量。

WITH 'Tom Hanks' AS actorName
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WHERE p.name = actorName
RETURN m.title AS movies
  • 1
  • 2
  • 3
  • 4

with重新定义范围

单子句查询
WITH  'toy story' AS mt, 'Tom Hanks' AS actorName
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WHERE p.name = actorName
AND toLower(m.title) CONTAINS mt
RETURN m.title AS movies
  • 1
  • 2
  • 3
  • 4
  • 5
多子句查询
WITH  'toy story' AS mt, 'Tom Hanks' AS actorName
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WITH m, toLower(m.title) AS movieTitle
WHERE p.name = actorName
AND movieTitle CONTAINS mt
RETURN m.title AS movies, movieTitle

// 变量 mt 和 actorName 可用于子句和子句,就像上一个查询一样。但是,这里的不同之处在于,我们必须将 m 添加到第二个子句中,以便可以使用该节点返回节点的标题。子句用于定义或重新定义变量的作用域。因为我们想要重新定义用于子句的内容,所以我们添加了一个新子句。这将为查询的其余部分创建一个新作用域,以便可以使用 m 和 movieTitle 返回值。如果要删除第二个子句中的 m,则查询将不会编译。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

定义表达式(例如,toLower(m.title))时,必须指定使用关键字定义的别名。AS

限制结果

WITH  'Tom Hanks' AS theActor
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WHERE p.name = theActor
RETURN m.title AS movies LIMIT 2
  • 1
  • 2
  • 3
  • 4
WITH  'Tom Hanks' AS theActor
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WHERE p.name = theActor
WITH m  LIMIT 2
RETURN m.title AS movies

// 使用此查询,将检索两个影片节点。此处的不同之处在于,您可以使用来限制稍后在查询中使用的 m 个节点数。将节点传递到下一个子句称为流水线
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

对限制结果进一步处理,进行排序

WITH  'Tom Hanks' AS theActor
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WHERE p.name = theActor
WITH m ORDER BY m.year LIMIT 5
RETURN m.title AS movies, m.year AS yearReleased
  • 1
  • 2
  • 3
  • 4
  • 5

with自定义返回节点属性

MATCH (n:Movie)
WHERE n.imdbRating IS NOT NULL
AND n.poster IS NOT NULL
WITH n {
  .title,
  .year,
  .languages,
  .plot,
  .poster,
  .imdbRating,
  directors: [ (n)<-[:DIRECTED]-(d) | d { tmdbId:d.imdbId, .name } ]
}
ORDER BY n.imdbRating DESC LIMIT 4
RETURN collect(n)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

此查询返回“影片”节点中的数据子集。它返回评分最高的四部电影。由于我们已指定 4 个限制,因此只有 4 个具有指定属性的对象添加到列表中。

虽然这非常适合在客户端进行处理,但它会在服务器上占用更多内存,因为记录无法流式传输到客户端,而是收集到服务器上的列表结构中。

with流水线查询

使我们能够将第一个查询的结果管道化到第二个查询中。通过这个简单的查询,m 不需要重新定义或限定范围。

聚合
MATCH (:Movie {title: 'Toy Story'})-[:IN_GENRE]->(g:Genre)<-[:IN_GENRE]-(m)
WHERE m.imdbRating IS NOT NULL
WITH g.name AS genre,
count(m) AS moviesInCommon,
sum(m.imdbRating) AS total
RETURN genre, moviesInCommon,
total/moviesInCommon AS score
ORDER By score DESC
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
聚合、流水线
MATCH (u:User {name: "Misty Williams"})-[r:RATED]->(:Movie)
WITH u, avg(r.rating) AS average
MATCH (u)-[r:RATED]->(m:Movie)
WHERE r.rating > average
RETURN average , m.title AS movie,
r.rating as rating
ORDER BY rating DESC
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
2步聚合
MATCH (m:Movie)<-[:ACTED_IN]-(a:Actor)
WHERE m.title CONTAINS 'New York'
WITH m, collect (a.name) AS actors,
count(*) AS numActors
ORDER BY numActors DESC
RETURN collect(m { .title, actors, numActors }) AS movies
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
尽早使用LIMIT
MATCH (p:Actor)
WHERE p.born.year = 1980
WITH p  LIMIT 3
MATCH (p)-[:ACTED_IN]->(m:Movie)-[:IN_GENRE]->(g:Genre)
WITH p, collect(DISTINCT g.name) AS genres
RETURN p.name AS actor, genres
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

unwind展开列表

UNWIND为列表的每个元素返回一行。
如:某节点有个属性为列表,UNWIND将列表中的元素迭代,每个元素返回一个结果

MATCH (m:Movie)-[:ACTED_IN]-(a:Actor)
WHERE a.name = 'Tom Hanks'
UNWIND m.languages AS lang
RETURN m.title AS movie,
m.languages AS languages,
lang AS language

// 一部汤姆·汉克斯(Tom Hanks)出演的电影被检索到。
// 语言属性(即列表)被解包,并且每个值都被引用为 lang。
// 返回的行将是电影标题和为多行重复的语言属性以及 lang 值。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
// 检索所有影片节点。
// 对于每个“电影”节点,它会展开语言列表以创建一个名为 lang 的列表。请注意,我们使用 trim() 函数来确保语言名称中没有多余的空格字符。
// 然后,我们使用列表的元素来查找使用该语言的所有电影。
// 最后,我们返回一行,其中包含每种语言名称以及该语言的最多 10 个电影标题的列表。
MATCH (m:Movie)
UNWIND m.languages AS lang
WITH m, trim(lang) AS language
WITH language, collect(m.title) AS movies
RETURN language, movies[0..10]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

trim() 函数来确保语言名称中没有多余的空格字符。

优化查询,减少内存

子查询

执行一系列子句时,检索到的所有节点和关系都在内存中。如果一组子句的内存要求超过配置的 VM,则查询将失败。

子查询是一组在其自己的范围内执行的 Cypher 语句。子查询通常从外部封闭查询调用。使用子查询,可以限制需要处理的行数。

以下是有关子查询的一些重要事项:

  • 子查询返回子句中的变量所引用的值。
  • 子查询不能返回与封闭查询中使用的同名的变量。
  • 必须将变量从封闭查询显式传递到子查询。
CALL执行子查询
子查询由此处的 {}分隔
CALL {
   MATCH (m:Movie) WHERE m.year = 2000
   RETURN m ORDER BY m.imdbRating DESC LIMIT 10
}
MATCH  (:User)-[r:RATED]->(m)
RETURN m.title, avg(r.rating)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
变量传递子查询

使用子查询可以减少查询中处理的行数

MATCH (m:Movie)
CALL {
    WITH m
    MATCH (m)<-[r:RATED]-(u:User)
     WHERE r.rating = 5
    RETURN count(u) AS numReviews
}
RETURN m.title, numReviews
ORDER BY numReviews DESC

// 第一个为每部电影返回一行,图中的 m。MATCH
// 它将 Movie 节点 m 传递给子查询。
// 然后在子查询中,执行查询以查找给予该电影 5 分级的所有用户,并对其进行计数。
// 子查询返回计数。
// 返回到封闭查询中,将返回标题,并从子查询返回的行数计数。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

UNION查询结果结合

合并查询结果

要合并的查询必须返回相同数量的属性或数据

MATCH (m:Movie) WHERE m.year = 2000
RETURN {type:"movies", theMovies: collect(m.title)} AS data
UNION ALL
MATCH (a:Actor) WHERE a.born.year > 2000
RETURN { type:"actors", theActors: collect(DISTINCT a.name)} AS data

// 这两个查询都返回一个名为 Data 的变量,因此我们可以使用 union all 来组合结果。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

UNION ALL返回所有结果,这些结果在内存上更有效,但可能导致重复。 返回不同的结果

与子查询一起用

UNION包装在子查询中,进一步处理结果

MATCH (p:Person)
WITH p LIMIT 100
CALL {
  WITH p
  OPTIONAL MATCH (p)-[:ACTED_IN]->(m:Movie)
  RETURN m.title + ": " + "Actor" AS work
UNION
  WITH p
  OPTIONAL MATCH (p)-[:DIRECTED]->(m:Movie)
  RETURN m.title+ ": " +  "Director" AS work
}
RETURN p.name, collect(work)

// 检索 100 个人员节点并将其传递到子查询。
// 如果该人在电影中表演过,则返回带有 Actor 后缀的标题。
// 子查询的第二部分对定向关系执行相同的操作。
// 合并并收集工作结果。
// 结果是该人的姓名及其演员或导演头衔。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

optional match 用于搜索模式中描述的匹配项, 对于找不到的项用null代替。类似于match, 区别在于如果没有匹配到, optional match会用null来作为未匹配到的部分的值

语句参数

设置参数

单个参数

:param actorName: 'Tom Hanks'
  • 1

多个参数

:params 
{
  "actorName": 'Tom Hanks'
}
  • 1
  • 2
  • 3
  • 4

设置整数

由于 JavaScript 和 Neo4j 类型系统中的整数之间存在差异,因此在设置参数时,任何整数都将转换为浮点值

:param number: 10
// 会默认将数字转换为浮点数
:param number=> 10
// 将数字强转为整数
  • 1
  • 2
  • 3
  • 4

多个参数

:params {actorName: 'Tom Cruise', movieName: 'Top Gun'}
  • 1

查询

MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
WHERE p.name = $actorName
AND m.title = $movieName
RETURN p, m
  • 1
  • 2
  • 3
  • 4

查看参数

:params
  • 1

删除参数

:params {}
  • 1

Python语法中传参示例

def get_actors(tx, movieTitle): 
  result = tx.run("""
    MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
    WHERE m.title = $title
    RETURN p
  """, title=movieTitle)

  return [ record["p"] for record in result ]

with driver.session() as session:
    result = session.read_transaction(get_actors, movieTitle="Toy Story")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

总结

以上是我个人在学习过程中的记录所学,希望对正在一起学习的小伙伴有所帮助!!!

cypher更多具体用法可,跳转至官方文档查看用例

参考链接:
The Neo4j Cypher Manual
【知识图谱】Neo4j Cypher查询语言详解
[知识图谱] 3.3-Cypher语言及语法使用

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/80458
推荐阅读
相关标签
  

闽ICP备14008679号