暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Neo4j系列二——What is Cypher?

EchoJoy 2020-08-23
667
每天进步一点点,即使不成功,也不至于空白!——三毛

3.1 What is Cypher?

Cypher是什么?

Cypher是一种声明式图数据库查询语言,它具有丰富的表现力,能高效地查询和更新图数据。

Cypher借鉴了SQL语言的结构——查询可由各种各样的语句组合。

例如,下面是查找名为'John'和'John'朋友的朋友的查询语句。

 MATCH (john {name: 'John'})-[:friend]->()-[:friend]->(fof)
 RETURN john.name, fof.name

接下来在语句中添加一些过滤。给定一个用户名列表,找到名字在列表中的所有节点。匹配他们的朋友,仅返回那些他们关注的name属性以'S'开头的用户。

 MATCH (user)-[:friend]->(follower)
 WHERE user.name IN ['Joe', 'John', 'Sara', 'Maria', 'Steve'] AND follower.name =~ 'S.*'
 RETURN user.name, follower.name

模式(Patterns)

Neo4j图由节点和关系构成。节点可能还有标签和属性,关系可能还有类型和属性。节点和关系都是简单的低层次的构建块。单个节点或者关系只能编码很少的信息,但模式可以将很多节点和关系编码为任意复杂的想法。

Cypher查询语言很依赖于模式。只包含一个关系的简单模式连接了一对节点。例如,一个人LIVES_IN在某个城市或者某个城市PART_OF一个国家。使用了多个关系的复杂模式能够表达任意复杂的概念,可以支持各种有趣的使用场景。例如,下面的Cypher代码将两个简单的模式连接在一起:

 (:Person) -[:LIVES_IN]-> (:City) -[:PART_OF]-> (:Country)

像关系数据库中的SQL一样,Cypher是一种文本的声明式查询语言。它使用ASCII 的形式来表达基于图的模式。采用类似SQL的语句,如MATCH,WHERE和DELETE,来组合这些模式以表达所预期的操作。

节点语法

Cypher采用一对圆括号()
来表示节点。如:(), (foo),使用中括号{}
表示节点的属性不同属性可用逗号隔开。下面是一些常见的节点表示法:

 ()
 (matrix)
 (:Movie)
 (matrix:Movie)
 (matrix:Movie {title: "The Matrix"})
 (matrix:Movie {title: "The Matrix", released: 1997})
 
 Match (matrix:Movie {title: "The Matrix"}) return matrix

Let's use Cypher to generate a small social graph.

 CREATE (ee:Person { name: "Emil", from: "Sweden", klout: 99 })
  • CREATE
    clause to create data

  • ()
    parenthesis to indicate a node

  • ee:Person
    a variable 'ee' and label 'Person' for the new node

  • brackets
    to add properties to the node

Now find the node representing Emil:

 MATCH (ee:Person) WHERE ee.name = "Emil" RETURN ee;
  • MATCH
    clause to specify a pattern of nodes and relationships

  • (ee:Person)
    a single node pattern with label 'Person' which will assign matches to the variable 'ee'

  • WHERE
    clause to constrain the results

  • ee.name = "Emil"
    compares name property to the value "Emil"

  • RETURN
    clause used to request particular results

CREATE
clauses can create many nodes and relationships at once.

 MATCH (ee:Person) WHERE ee.name = "Emil" RETURN ee
 CREATE (js:Person { name: "Johan", from: "Sweden", learn: "surfing" }),
 (ir:Person { name: "Ian", from: "England", title: "author" }),
 (rvb:Person { name: "Rik", from: "Belgium", pet: "Orval" }),
 (ally:Person { name: "Allison", from: "California", hobby: "surfing" }),
 (ee)-[:KNOWS {since: 2001}]->(js),(ee)-[:KNOWS {rating: 5}]->(ir),
 (js)-[:KNOWS]->(ir),(js)-[:KNOWS]->(rvb),
 (ir)-[:KNOWS]->(js),(ir)-[:KNOWS]->(ally),
 (rvb)-[:KNOWS]->(ally)

关系语法

Cypher使用一对短横线(即--
)表示:一个无方向关系。有方向的关系在其中一段加上一个箭头(即<--
-->
)。方括号表达式[…]
可用于添加详情。里面可以包含变量、属性和或者类型信息。关系的常见表达方式如下:

 --
 -->
 -[role]->
 -[:ACTED_IN]->
 -[role:ACTED_IN]->
 -[role:ACTED_IN {roles: ["Neo"]}]->
 
  Match (n)-[role]->(m) return n, role ,m limit 10

模式语法

将节点和关系的语法组合在一起可以表达模式。

 match (keanu:Person:Actor {name: "Keanu Reeves"})-[role: ACTED_IN {roles: ["Neo"]}]->(matrix:Movie {title: "The Matrix"}) return keanu

For instance, a pattern can be used to find Emil's friends:  

 MATCH (ee:Person)-[:KNOWS]-(friends)
 WHERE ee.name = "Emil" RETURN ee, friends
  • MATCH
    clause to describe the pattern from known Nodes to found Nodes

  • (ee)
    starts the pattern with a Person (qualified by WHERE)

  • -[:KNOWS]-
    matches "KNOWS" relationships (in either direction)

  • (friends)
    will be bound to Emil's friends

Pattern matching can be used to make recommendations. Johan is learning to surf, so he may want to find a new friend who already does:

 MATCH (js:Person)-[:KNOWS]-()-[:KNOWS]-(surfer)
 WHERE js.name = "Johan" AND surfer.hobby = "surfing"
 RETURN DISTINCT surfer
  • ()
    empty parenthesis to ignore these nodes

  • DISTINCT
    because more than one path will match the pattern

  • surfer
    will contain Allison, a friend of a friend who surfs

使用可视化查询计划:

通过预先解释或配置文件来了解您的查询是如何工作的:

 PROFILE MATCH (js:Person)-[:KNOWS]-()-[:KNOWS]-(surfer)
 WHERE js.name = "Johan" AND surfer.hobby = "surfing"
 RETURN DISTINCT surfer

事务

任何更新图的查询都运行在一个事务中。一个更新查询要么全部成功,要么全部失败。Cypher或者创建一个新的事务,或者运行在一个已有的事务中:

  • 如果运行上下文中没有事务,Cypher将创建一个,一旦查询完成就提交该事务。

  • 如果运行上下文中已有事务,查询就会运行在该事务中。直到该事务成功地提交之后,数据才会持久化到磁盘中去。

兼容性

Cypher不是一成不变的语言。新版本引入了很多新的功能,一些旧的功能可能会被移除。如果需要,旧版本依然可以访问到。这里有两种方式在查询中选择使用哪个版本:

  • 为所有查询设置版本:可以通过neo4j.conf中cypher.default_language_version参数来配置Neo4j数据库使用哪个版本的Cypher语言。

  • 在查询中指定版本:简单地在查询开始的时候写上版本,如Cypher 2.3。

电影图案例(完整代码)

电影图表是一个包含演员和导演的迷你图表应用程序,这些演员和导演通过他们合作的电影有联系。

This guide will show you how to:

  1. Create: insert movie data into the graph

  2. Find: retrieve individual movies and actors

  3. Query: discover related actors and directors

  4. Solve: the Bacon Path

由于代码很长,后台回复【666】获取资料链接,或者自行到官网也可以获取。

Find操作

Find the actor named "Tom Hanks"...

 MATCH (tom {name: "Tom Hanks"}) RETURN tom

Find the movie with title "Cloud Atlas"...

 MATCH (cloudAtlas {title: "Cloud Atlas"}) RETURN cloudAtlas

Find 10 people...

 MATCH (people:Person) RETURN people.name LIMIT 10

Find movies released in the 1990s...

 MATCH (nineties:Movie) WHERE nineties.released >= 1990 AND nineties.released < 2000 RETURN nineties.title
Query 操作

List all Tom Hanks movies...

 MATCH (tom:Person {name: "Tom Hanks"})-[:ACTED_IN]->(tomHanksMovies) RETURN tom,tomHanksMovies

Who directed "Cloud Atlas"?

 MATCH (cloudAtlas {title: "Cloud Atlas"})<-[:DIRECTED]-(directors) RETURN directors.name

Tom Hanks' co-actors...

 MATCH (tom:Person {name:"Tom Hanks"})-[:ACTED_IN]->(m)<-[:ACTED_IN]-(coActors) RETURN coActors.name

How people are related to "Cloud Atlas"...

 MATCH (people:Person)-[relatedTo]-(:Movie {title: "Cloud Atlas"}) RETURN people.name, Type(relatedTo), relatedTo
Solve 操作

“六度凯文·培根”:这是一个简单的最短路径查询,称为“Bacon路径”。

  1. Variable length patterns

  2. Built-in shortestPath() algorithm

Movies and actors up to 4 "hops" away from Kevin Bacon

 MATCH (bacon:Person {name:"Kevin Bacon"})-[*1..4]-(hollywood)
 RETURN DISTINCT hollywood

Bacon path, the shortest path of any relationships to Meg Ryan

 MATCH p=shortestPath(
 (bacon:Person {name:"Kevin Bacon"})-[*]-(meg:Person {name:"Meg Ryan"})
 )
 RETURN p

Note:you only need to compare property values like this when first creating relationships.

Recommend

Extend Tom Hanks co-actors, to find co-co-actors who haven't worked with Tom Hanks...(查找没有与Tom Hanks合作过的演员z)

 MATCH (tom:Person {name:"Tom Hanks"})-[:ACTED_IN]->(m)<-[:ACTED_IN]-(coActors),
   (coActors)-[:ACTED_IN]->(m2)<-[:ACTED_IN]-(cocoActors)
 WHERE NOT (tom)-[:ACTED_IN]->()<-[:ACTED_IN]-(cocoActors) AND tom <> cocoActors
 RETURN cocoActors.name AS Recommended, count(*) AS Strength ORDER BY Strength DESC

Find someone to introduce Tom Hanks to Tom Cruise

 MATCH (tom:Person {name:"Tom Hanks"})-[:ACTED_IN]->(m)<-[:ACTED_IN]-(coActors),
   (coActors)-[:ACTED_IN]->(m2)<-[:ACTED_IN]-(cruise:Person {name:"Tom Cruise"})
 RETURN tom, m, coActors, m2, cruise
Clean up

When you're done experimenting, you can remove the movie data set.

Note:

  1. Nodes can't be deleted if relationships exist

  2. Delete both nodes and relationships together

WARNING: This will remove all Person and Movie nodes!

Delete all Movie and Person nodes, and their relationships

 MATCH (n) DETACH DELETE n
 

Note you only need to compare property values like this when first creating relationships

Prove that the Movie Graph is gone

 MATCH (n) RETURN n

3.2Cypher基本语法

3.2.1类型

Cypher处理的所有值都有一个特定的类型,它支持如下类型:

  • 数值型

  • 字符串

  • 布尔型

  • 节点

  • 关系

  • 路径

  • 映射(Map)

  • 列表(List)

3.2.2表达式

Cypher中的表达式如下:

  • 十进制(整型和双精度型)的字面值:13, -4000, 3.14, 6.022E23

  • 十六进制整型字面值(以0x开头):0x13zf, 0xFC3A9, -0x66eff

  • 八进制整型字面值(以0开头):01372, 02127, -05671

  • 字符串字面值:'Hello', "World"

  • 布尔字面值:true, false, TRUE, FALSE

  • 变量:n, x, rel, myFancyVariable, A name with weird stuff in it[]!

  • 属性:n.prop, x.prop, rel.thisProperty, myFancyVariable. (weird property name)

  • 动态属性:n["prop"], rel[n.city + n.zip], map[coll[0]]

  • 参数:$param, $0

  • 表达式列表:['a', 'b'], [1, 2, 3], ['a', 2, n.property, $param], [ ]

  • 函数调用:length(p), nodes(p)

  • 聚合函数:avg(x.prop), count(*)

  • 路径-模式:(a)-->()<--(b)

  • 计算式:1 + 2 >3 and 3 < 4.

  • 返回true或者false的断言表达式:a.prop = 'Hello', length(p) >10, exists(a.name)

  • 正则表达式:a.name =~ 'Tob.*'

  • 大小写敏感的字符串匹配表达式:a.surname STARTS WITH 'Sven', a.surname ENDS WITH 'son' or a.surname CONTAINS 'son'

  • CASE表达式

3.2.3转移字符

Cypher中的字符串可以包含如下转义字符:

字符含义
\t制表符
\b退格
\n换行
\r回车
\f换页
'单引号
"双引号
\反斜杠
\uxxxxUnicode UTF-16编码点(4位的十六进制数字必须跟在\u后面)
\UxxxxxxxxUnicode UTF-32   编码点(8位的十六进制数字必须跟在\U后面)
3.2.4Case表达式

计算表达式的值,然后依次与WHEN语句中的表达式进行比较,直到匹配上为止。如果未匹配上,则ELSE中的表达式将作为结果。如果ELSE语句不存在,那么将返回null。

  • 语法:

     CASE test
     WHEN value THEN result
     [WHEN ...]
     [ELSE default]
     END
  • 参数

    • test:一个有效的表达式

    • value:一个表达式,它的结果将与test表达式的结果进行比较

    • result:如果value表达式能够与test表达式匹配,它将作为结果表达式

    • default:没有匹配的情况下的默认返回表达式

  • 查询

     MATCH (n)
     RETURN
     CASE n.eyes
     WHEN 'blue'
     THEN 1
     WHEN 'brown'
     THEN 2
     ELSE 3 END AS result

一般的Case表达式

 CASE 
 WHEN predicate THEN result
 [WHEN ...]
 [ELSE default]
 END

参数:

  • predicate:判断的断言,以找到一个有效的可选项

  • result:如果predicate匹配到,result就作为结果表达式

  • default:没有匹配到的情况下,默认返回表达式

 MATCH (n)
 RETURN
 CASE
 WHEN n.eyes='blue'
 THEN 1
 WHEN n.age<30
 THEN 2
 ELSE 3 END AS result
3.2.5变量

当需要引用模式(pattern)或者查询的某一部分的时候,可以对其进行命名。针对不同部分的这些命名被称为变量。变量是区分大小写的。例如:

 MATCH (n)-[r]->(b) RETURN b 

这里的n和b和r就是变量。

3.2.6参数

Cypher支持带参数的查询。这意味着开发人员不是必须用字符串来构建查询。此外,这也让执行计划的缓存更容易。

参数能够用于WHERE语句中的字面值和表达式,START语句中的索引值,索引查询以及节点和关系的id。参数不能用于属性名、关系类型和标签,因为这些模式(pattern)将作为查询结构的一部分被编译进查询计划。

合法的参数名是字母,数字以及两者的组合。下面是一个使用参数的完整例子。参数以JSON格式提供。具体如何提交它们取决于所使用驱动程序。

  • 字符串

    • 参数

       {
       "name" : "Johan"
       }
       Match (n) where n.name=$name return n
3.2.7运算符
  • 数学运算符 :包括+,-,*,/ 和%,^。

  • 比较运算符 :包括=,<>,<,>,<=,>=,IS NULL和IS NOT NULL。

  • 布尔运算符 :包括AND,OR,XOR和NOT。

  • 字符串运算符 :连接字符串的运算符为+。正则表达式的匹配运算符为=~

  • 列表运算符 :列表的连接也可以通过+运算符。可以用 IN
    来检查列表中是否存在某个元素。

  • 值的相等与比较 :Cypher支持使用=和<>来比较两个值的相等/不相等关系。同类型的值只有它们是同一个值的时候才相等,如3 = 3和"x" <> "xy"。

  • 值的排序与比较:比较运算符<=,<(升序)和>=,>(降序)可以用于值排序的比较。如下所示:

    • 数字型值的排序比较采用数字顺序

    • java.lang.Double.NaN大于所有值

    • 字符串排序的比较采用字典顺序。如"x" < "xy"

    • 布尔值的排序遵循false < true

    • 当有个参数为null的时候,比较结果为null。如null < 3的结果为null

    • 将其他类型的值相互比较进行排序将报错

  • 链式比较运算:比较运算可以被任意地链在一起。如x < y <= z等价于x < y AND y <= z。如:

     MATCH (n) WHERE 21 < n.age <= 30 RETURN n
     //等价于
     MATCH (n) WHERE 21 < n.age AND n.age <= 30 RETURN n
3.2.8注释

Cypher语言的注释类似其他语言,用双斜线//来注释行。例如:

 MATCH (n) RETURN n //这是行末尾注释
 MATCH (n)
 //这是整行注释
 RETURN n
 MATCH (n) WHERE n.property = '//这不是注释' RETURN n
3.2.9模式(Patterns)

使用模式可以描述你期望看到的数据的形状。例如,在MATCH、CREATE、DELETE等语句中,当用模式描述一个形状的时候,Cypher将按照模式来获取相应的数据。模式描述数据的形式很类似在白板上画出图的形状。通常用圆圈来表达节点,使用箭头来表达关系。

  • 节点模式

    模式能表达的最简单的形状就是节点。节点使用一对圆括号表示,然后中间含一个名字。例如:(a)
    。这个模式描述了一个节点,其名称使用变量a表示。

  • 关联节点的模式

    模式可以描述多个节点及其之间的关系。Cypher使用箭头来表达两个节点之间的关系。例如:

     (a)-->(b)
     (a)-->(b)<--(c)
     //节点的命名仅仅当后续的模式或者Cypher查询中需要引用时才需要。如果不需要,则命名可以省略。如:
     (a)-->()<--(c)
  • 标签

    模式除了可以描述节点之外,还可以用来描述标签。比如:

     (a:User)-->(b)
     //也可以描述一个节点的多个标签,如:
     (a:User:Admin)-->(b)
  • 指定属性

    属性在模式中使用键值对的映射结构来表达,然后用大括号包起来。例如,一个有两个属性的节点如下所示:

     (a {name: 'Andres', sport: 'Brazilian Ju-Jitsu'}) 
     //关系中的属性:
     (a)-[{blocked: false}]->(b)

    当模式中有属性时,它实际上为数据增加了额外的约束。在CREATE中,属性会被增加到新创建的节点和关系中。在MERGE语句中,属性将作为一个约束去匹配数据库中数据是否存在该属性。如果没有匹配到,MERGE和CREATE的行为一样,属性会被增加到新创建的节点和关系中。

  • 描述关系

    如前面的所做例子所示,可以用箭头简单地描述两个节点之间的关系。它描述了关系的存在性和方向性。但如果不关心关系的方向,则箭头的头部可以省略。例如:(a)--(b)

    与节点类似,如果后续需要引用到该关系,则可以给关系赋一个变量名。变量名需要用方括号括起来,放在箭头的短横线中间,如下所示:(a)-[r]->(b)

    就像节点有标签一样,关系可以有类型(type)。给关系指定类型,如下所示:(a)-[r:REL_TYPE]->(b)

    不像节点可以有多个标签,关系只能有一个类型。但如果所描述的关系可以是一个类型集中的任意一种类型,可以将这些类型都列入到模式中,它们之间以竖线“|”分割。如:(a)-[r:TYPE1|TYPE2]->(b)

    注意:这种模式仅适用于描述已经存在的数据(如在MATCH语句中),而在CREATE或者MERGE语句中是不允许的,因为一个关系不能创建多个类型

    与节点类似,关系的命名也是可以省略的。如:(a)-[:REL_TYPE]->(b)

    与使用一串节点和关系来描述一个长路径的模式不同,很多关系(以及中间的节点)可以采用指定关系的长度的模式来描述。例如:(a)-[*2]->(b)

    它描述了一张三个节点和两个关系的图。这些节点和关系都在同一条路径中(路径的长度为2)。它等同于:(a)-->()-->(b)

    关系的长度也可以指定一个范围,这被称为可变长度的关系。例如:(a)-[*3..5]->(b)

    关系的长度最小值为3,最大值为5。它描述了一个或者有4个节点和3个关系,或者5个节点4个关系,或者6个节点和5个关系连在一起的图组成的一条路径。

    长度的边界也是可以省略的,如描述一个路径长度大于等于3的路径:(a)-[*3..]->(b)
    路径长度小于等于5的路径,如:(a)-[*..5]->(b)

    两个边界都可以省略,这允许任意长度的路径,如:(a)-[*]->(b)

     match (me)-[:KNOWS*1..2]-(remore_friend) 
     where me.name ='Filipa'
     return remote_friend.name
  • 列表Cypher对列表(list)有很好的支持。可以使用方括号和一组以逗号分割的元素来创建一个列表。例如:RETURN [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] AS list

    return range(0,10)
    :制定了列表包含元素的开始数字和结束数字,两端也是被包含在内。

  • 空值

    空值null在Cypher中表示未找到或者未定义。从概念上讲,null意味着”一个未找到的未知值”。对待null会与其他值有些不同。例如从节点中获取一个并不存在的属性将返回null。大多数以null作为输入的表达式将返回null。这包括WHERE语句中用于断言的布尔表达式。

    null不等于null。两个未知的值并不意味着它们是同一个值。因此,null = null返回null而不是true。判断 某个节点上 有或没有 某个属性,如下:

     Match  (n)  where n.name  is null return n
     Match  (n)  where n. name  is not  null return n
    • 空值的逻辑运算

      逻辑运算符(包括AND,OR,XOR,IN,NOT)把null当作未知的三值逻辑值。下面为AND,OR和XOR的逻辑值表。

      aba AND ba OR ba XOR b
      falsefalsefalsefalsefalse
      falsenullfalsenullnull
      falsetruefalsetruetrue
      truefalsefalsetruetrue
      truenullnulltruenull
      truetruetruetruefalse
      nullfalsefalsenullnull
      nullnullnullnullnull
      nulltruenulltruenull
  • 空值与IN

    IN运算符遵循类似的逻辑。如果列表中存在某个值,结果就返回true。如果列表包含null值并且没有匹配到值,结果返回null。否则结果为false。下面表中是一些例子:

    表达式结果
    2 IN [1, 2, 3]true
    2 IN [1, null, 3]null
    2 IN [1, 2, null]true
    2 IN [1]false
    2 IN []false
    null IN [1, 2, 3]null
    null IN [1, null, 3]null
    null IN []false

    all, any, none和single与IN类似,如果可以确切地计算结果,将返回true或者false。否则将返回null。

  • 返回空值的表达式

    • 从列表中获取不存在的元素:[][0]
      head([])

    • 试图访问节点或者关系的不存在的属性:n.missingProperty

    • 与null做比较:1 < null

    • 包含null的算术运算:1 + null

    • 包含任何null参数的函数调用:sin(null)


- END -

学习图形数据库Neo4j也是因为公司项目开发需要,而且也是刚开始学习,自己也找了些学习资料,如果有小可爱需要,添【lxcecho】联系我获取,一块学习交流探讨。

最后,请素质三连,点赞、在看、转发,关注并标星公众号 Just For Joy 获取最新内容,后台回复 666 获取学习近期学习笔记,更多内容陆续奉上。



文章转载自EchoJoy,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论