目录

Cypher手册详解

1 背景

2 唯一性

3 语法

3.1 命名规则

3.2 表达式

3.3 变量与保留关键字

3.4 参数

3.5 操作符

3.6 模式

3.7 列表


Cypher手册详解

最近在研究知识图谱,避免不了的涉及到了图数据库和图算法,我们用的图数据库是neo4j,对其CQL语法做一个记录。整篇文章是对官网Cypher手册的翻译(正常访问超级慢,也许要翻墙),同时做了一些删减,例如地理函数和时间函数,和我的项目关系不大,就没有学习,对于官网的一些示例加上了结果的截图和自己的理解,本博文基于Neo4j3.5.3,其余版本可能会报错。如有错误,还麻烦各位大佬指正,非常感谢。

1 背景

什么是neo4j?

Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中。它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储在网络(从数学角度叫做图)上而不是表中。Neo4j也可以被看作是一个高性能的图引擎,该引擎具有成熟数据库的所有特性。程序员工作在一个面向对象的、灵活的网络结构下而不是严格、静态的表中--但是他们可以享受到具备完全的事务特性、企业级的数据库的所有好处。

neo4j的呈现形式:Neo4j中不存在表的概念,只有两类:节点(Node)和关系(Relation),可以简单理解为图里面的点和边。

在数据查询中,节点一般用小括号(),关系用中括号[]。

当然也隐含路径的概念,是用节点和关联表示的,如:(a)-[r]->(b),表示一条从节点a经关联r到节点b的路径。

关系:neo4j中是单向关系,严格的来说不具备双向或者无向的关系。但是merge (a)-[r]-(b)这样的语句创建的关系可以理解为是双向的,但是neo4j中比较尴尬的一点是这样可以理解为无向关系的关系,在web呈现时是带着单向箭头的。

属性:节点和关系都可以具备属性。

标签:代表节点的类型,一个节点可以有0个、1个或者多个标签。

类型:代表关系的类型,一条关系可以有0个或者1个,一条边不能具有多个type。

2 唯一性

在模式匹配时,neo4j确保不会在单个模式中多次找到相同图形关系的匹配。举例,在寻找朋友的朋友时,不会返回所述用户自身。

CREATE (adam:User { name: 'Adam' }),(pernilla:User { name: 'Pernilla' }),(david:User { name: 'David'}),(adam)-[:FRIEND]->(pernilla),(pernilla)-[:FRIEND]->(david)

寻找Adam朋友的朋友

MATCH (user:User { name: 'Adam' })-[r1:FRIEND]-()-[r2:FRIEND]-(friend_of_a_friend)

RETURN friend_of_a_friend.name AS fofName

返回David

因为r1和r2在同一个模式中,又是不同的变量名,所以不会返回同一条关系,即图形中的有向边。检验:在两个子句中用不同的变量名就不管用

MATCH (user:User { name: 'Adam' })-[r1:FRIEND]-(friend)

MATCH (friend)-[r2:FRIEND]-(friend_of_a_friend)

RETURN friend_of_a_friend.name AS fofName

但是只要在一个模式中,即使拆分了多个子模式也不会匹配到同一关系,如下所示。

MATCH (user:User { name: 'Adam' })-[r1:FRIEND]-(friend),(friend)-[r2:FRIEND]-(friend_of_a_friend)

RETURN friend_of_a_friend.name AS fofName

3 语法

3.1 命名规则

必须以字母开头,不能以数字开头。

节点标签:驼峰式命名,关系类型:全大写命名。

3.2 表达式

十进制、十六进制:0x13ff,0xFCA39

八进制整数文字:01372、02127

字符串、bool类型

属性:n.prop、x.prop、rel.thisProperty

动态属性: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)

聚合函数,路径模式

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

字符串匹配:

surname STARTS WITH 'Sven',

surname ENDS WITH 'son' or a.surname CONTAINS 'son'

CASE表达式

3.2.1 字符串常用的转义序列

\t Tab键 \b 后退键 \n 新起一行 \r 回车符 \f 制表符 \’ 单引号 \’’双引号

\\ 反斜杠的转义

3.2.2 CASE表达式

计算表达式,并按顺序与WHEN子句进行比较,直到找到匹配项。 如果未找到匹配项,则返回ELSE子句中的表达式。 但是,如果没有ELSE情况且未找到匹配项,则返回null。

CASE test

WHEN value THEN result

[WHEN ...]

[ELSE default]

END

建表语句:

create (A:Person {name:'Alice', eyes:"brown",age:38}),

(B:Person {name:"Bob", eyes:"blue", age:25}),

(C:Person {name:"Charlie", eyes:'green',age:53}),

(D:Person {name:"Daniel", eyes:'brown'}),

(E:Person {name:'Eskil',eyes:"blue",age:41,array:['one','two','three']}),

(A)-[:KNOWS]->(B),

(A)-[:KNOWS]->(C),

(B)-[:KNOWS]->(D),

(C)-[:KNOWS]->(D),

(B)-[:MARRIED]->(E)

测试语句1:

MATCH (n:Person)

RETURN n.name,

CASE n.eyes

WHEN 'blue'

THEN 1

WHEN 'brown'

THEN 2

ELSE 3 END AS result

测试语句2:

MATCH (n:Person)

RETURN n.name,

CASE

WHEN n.eyes = 'blue'

THEN 1

WHEN n.age < 40

THEN 2

ELSE 3 END AS result

测试语句3:

我们看到建表语句中,存在一些节点时没有age属性的,我们希望返回一个age_10_years_ago的值,假设不存在age属性,将该值返回-1。我们按照如下的方式来试写查询语句,期望对于Daniel返回-1,因为他不具备age属性。但是并不如意:

MATCH (n:Person)

RETURN n.name,

CASE n.age

WHEN n.age IS NULL THEN -1

ELSE n.age - 10 END AS age_10_years_ago

原因:n.age是一个整型,而n.age IS NULL是一个bool值,所以不会走到WHEN n.age IS NULL THEN -1这个对应的分支,需要换成如下的写法:

MATCH (n:Person)

RETURN n.name,

CASE

WHEN n.age IS NULL THEN -1

ELSE n.age - 10 END AS age_10_years_ago

换一种方式理解,就是常用的switch(n.age), 不会等于 n.age is null这个case ,想要返回-1直接写成如下方式即可。

MATCH (n:Person)

RETURN n.name,

CASE n.age

WHEN NULL THEN -1

ELSE n.age - 10 END AS age_10_years_ago

3.3 变量与保留关键字

变量仅在同一查询部分中可见

变量不会转移到后续查询中。 如果使用WITH将多个查询部分链接在一起,则必须在WITH子句中列出变量以将其转移到下一部分。

保留关键字不能用于变量名、函数名、参数。

3.4 参数

Cypher支持使用参数查询。这意味着开发人员不必使用字符串构建来创建查询。此外,参数使得Cypher的执行计划缓存更加容易,从而缩短了查询执行时间。

参数可用于:文字和表达式

节点和关系id

仅用于显式索引:索引值和查询

参数不能用于以下构造,因为它们构成了编译到查询计划中的查询结构的一部分:

属性键;所以,MATCH(n)WHERE n.$ param ='something'无效

关系类型

标签

参数可以包含字母和数字,以及这些参数的任意组合,但不能以数字或货币符号开头。

3.4.1 参数定义

参数仅仅对当前会话有效,网页刷新变量消失。变量为一个kv的键值对。

:param a:1, b:2或者:param {a: 1, b: 2}以这样的形式来定义参数,注意前面是有冒号的。

MATCH (n:Person)

WHERE n.name = $name

RETURN n

MATCH (n:Person { name: $name })

RETURN n

查看当前的所有参数:

:params

3.4.2 可以使用参数的各种场景

正则表达式:

:param {"regex":".*VM.*"}

match (n:VM) where n.name=~ $regex return n.name

大小写敏感的字符串匹配

:params { "name" : "Michael"}

MATCH (n:Person)

WHERE n.name STARTS WITH $name

RETURN n.name

创建多个带属性带标签的节点

:param {"props" : [ {

"awesome" : true,

"name" : "Andy",

"position" : "Developer"

}, {

"children" : 3,

"name" : "Michael",

"position" : "Developer"

} ]}

UNWIND $props AS properties

CREATE (n:Person)

SET n = properties

RETURN n

判断某个变量在或者不在变量列表中

:param "ids" : [ 0, 1, 2 ]

//判断变量在列表中,如何判断变量不在对应的列表中?not in会报错,<>达不到想要的结果

MATCH (n)

WHERE id(n) IN $ids

RETURN n.name

//判断变量不存在于列表中

match(n:VM) where size([l in [id(n)] where l in $ids ])=0 return n

调用函数

:param "value" : "Michaela"

START n=node:people(name = $value)

RETURN n

3.5 操作符

3.5.1 使用[]

来访问动态计算的属性键 对多个属性键来进行共同筛选

CREATE (a:Restaurant { name: 'Hungry Jo', rating_hygiene: 10, rating_food: 7 }),(b:Restaurant { name: 'Buttercup Tea Rooms', rating_hygiene: 5, rating_food: 6 }),(c1:Category { name: 'hygiene' }),(c2:Category { name: 'food' })

WITH a, b, c1, c2

MATCH (restaurant:Restaurant),(category:Category)

WHERE restaurant["rating_" + category.name]> 6

RETURN DISTINCT restaurant.name

3.5.2 ^完成指数运算

3.5.3字符串判断

STARTS WITH       ENDS WITH  CONTAINS

3.5.4 使用in进行更加复杂的列表成员操作

RETURN [2, 1] IN [1,[2, 1], 3] AS inList 会return true。

RETURN [1, 2] IN [1, 2] AS inList  会return false 这里的in不是判断认为两个是整体,而是将左边作为一个整体元素,判断左边是否为右边的子元素

如下查询可以用于判断llhs是否至少包含一个也存在于lrhs中的元素

MATCH (n)//判断当前库中的所有节点,有哪些的标签是Person或者Employee

WHERE size([l IN labels(n) WHERE l IN ['Person', 'Employee'] | 1]) > 0

RETURN count(n)

3.5.5 用[]获取列表元素

WITH ['Anne', 'John', 'Bill', 'Diane', 'Eve'] AS names

RETURN names[1..3] AS result

这里的方括号是左闭右开的,

所以会返回[‘John’,‘Bill’]

和C语言一样//表示对应的注释

3.6 模式

模式和模式匹配时Cypher的核心,有效使用Cypher需要对模式有一个正确的理解。

最为简单的模式就是一个双括号括上一个变量名,例如(a) a就是一个变量名

(a)-->(b)

(a)-->(b)<--(c)这样的一系列的节点和关系称之为路径

可以在模式中描述的最简单的属性称之为标签(a:User)-->(b)   同时可以描述具备多个标签的节点(a:User:Admin)-->(b)

3.6.1 指定属性

对于MERGE子句,属性将用作任何现有数据必须具有的形状的附加约束(指定的属性必须与图中的任何现有数据完全匹配)。 如果未找到匹配的数据,则MERGE的行为类似于CREATE,并且将在新创建的节点和关系中设置属性。

3.6.2 关系的模式

类似于节点的标签,对于关系来说叫做类型,但是和节点标签不同的是,关系的类型仅仅只有一种。如果我们想要描述一些数据,使得这种关系可以有一组类型中的任何一种,那么它们都可以在模式中列出,用管道符号将它们分开。像这样(但是仅仅适用于match,不适用于Create和merge):

(a)-[r:TYPE1|TYPE2]->(b)

关系名称通常也可以省略

3.6.3 变量长度的模式匹配

在模式的关系描述中指定长度来进行对应的描述

(a)-[*2]->(b)  等价于  (a)-->()-->(b)

(a)-[*3..5]->(b)这一关系是左闭右闭,即包含3个关系、4个关系、5个关系

(a)-[*3..]->(b)    (a)-[*..5]->(b)

需要特别注意的一点是,即使关系是单向的,在如下的语句中,--表示不考虑关系的方向,仍然会反向查找找出走一个关系或者两个关系的节点。

MATCH (me)-[:KNOWS*1..2]-(remote_friend)

WHERE me.name = 'Filipa'

RETURN remote_friend.name

3.7 列表

RETURN range(0, 10) as list ,range(0, 10)[3] as result//将列表中下标索引为3的元素也就是第4个元素返回

与Python不同的是 这里的range是左闭右闭的,即一个列表中有11个元素

range(0, 10)[-3]//倒数第三个元素

RETURN range(0, 10)[0..3]//左闭右开

RETURN range(0, 10)[-5..]或者[..4]//只有在list中的a..b是左闭右开的,路径长度的匹配与range范围中的a..b都左闭右闭的。

//也可以理解为返回倒数5个元素的列表和正数4个元素的列表

RETURN size(range(0, 10)[0..3])//size函数的返回结果是3

3.7.1 列表推导

RETURN [x IN range(0,10) WHERE x % 2 = 0 | x^3] AS result//这里的竖线不是或,而是管道

MATCH (a:Person { name: 'Charlie Sheen' })

RETURN [(a)-->(b) WHERE b:Movie | b.year] AS years

3.8 映射

Cypher坚定地支持映射,对map的处理不太理解。

3.9 使用null

Cypher中的null表示缺失或未定义的值,null并不等于null,不知道的两个值并不意味着它们相等 ,所以null=null会抛出null而不是true

null IN [1, 2, 3]

null IN [1, null, 3]

null in []

如果使用null来做列表切片的首尾索引值,那么返回值也是null。

原文地址:https://blog.csdn.net/weixin_42348333/article/details/89758617

Neo4j Cypher语法(一)的更多相关文章

  1. Neo4j Cypher语法(三)

    目录 5 函数 5.1 谓词函数 5.2 标量函数 5.3 聚合函数 5.4 列表函数 5.5 数学函数 5.6 字符串函数 5.7 Udf与用户自定义函数 6 模式 6.1 索引 6.2 限制 7 ...

  2. Neo4j Cypher语法(二)

    目录 4 子句 4.1 CREATE 4.2 MATCH 4.3 Match 4.4 Create match return连用来返回一个关系基础 4.5 Optional_match 4.6 Wit ...

  3. Neo4j 第六篇:Cypher语法

    Cypher是图形数据库查询语言事实上的标准. 一,Cypher类型系统 Cypher支持的类型系统分为三类:属性类型,复合类型和结构类型. 1,属性类型 属性类型:Integer.Float.Str ...

  4. 记录Neo4j上写的简单cypher语法

    neo4j是一个高性能的图形数据库,既然是数据库,那么主要操作就是增.删.改.查.所以进入正题: 一.CREATE:创建 语法如下: 1.create(变量名:标签名) :建立一个标签为Animal的 ...

  5. Cypher语法

    cypher是neo4j官网提供的声明式查询语言,非常强大,用它可以完成任意的图谱里面的查询过滤,我们知识图谱的一期项目 基本开发完毕,后面会陆续总结学习一下neo4j相关的知识.今天接着上篇文章来看 ...

  6. Neo4j Cypher查询语言详解

    Cypher介绍 "Cypher"是一个描述性的图形查询语言,允许不必编写图形结构的遍历代码对图形存储有表现力和效率的查询.Cypher还在继续发展和成熟,这也就意味着有可能会出现 ...

  7. Neo4j Cypher运行示例

    示例来源: Neo4j in Action. 0 准备数据 0.1 node (user1 { name: 'John Johnson', type: 'User', email: 'jsmith@e ...

  8. neo4j 基本语法笔记(全)

    按照总监要求看了两天的neo4j 数据库的使用.在网上找了一个基础教程类似于w3c.school的网站(英文 ,中文,中文的翻译的不是很好,如果英文不好可以辅助理解),这个教程基础知识很全全面,从数据 ...

  9. Neo4j/cypher学习笔记与学习建议

    简介 本笔记的主要内容是 cypher 查询语言的编写与使用. 笔记主要整理自w3cschool上的neo4j教程以及Neo4j中文网所提供的cypher中文文档,此外还包括少量从其他个人博客与官方手 ...

随机推荐

  1. centos6.9实现双网卡绑定

    1.创建bond0文件 # vi /etc/sysconfig/network-scripts/ifcfg-bond0 DEVICE=bond0 NM_CONTROLLED=no #是否由networ ...

  2. Linux设备驱动程序 之 获取当前时间

    墙上时间 内核一般通过jiffies来获取当前时间,该数值表示的是最近一次系统启动到当前的时间间隔,它和设备驱动程序无关,因为它的声明期只限于系统的运行期:但是驱动程序可以用jiffies来计算不同事 ...

  3. Nginx之共享内存与slab机制

    1. 共享内存 在 Nginx 里,一块完整的共享内存以结构体 ngx_shm_zone_t 来封装,如下: typedef struct ngx_shm_zone_s ngx_shm_zone_t; ...

  4. nginx 的使用

    nginx 反向代理,并拥有其高效的性能,并发效果好,是解决跨域最好的选择 nginx 的使用 1. 下载:在官网上下载 window 系统的 nginx 网址:http://nginx.org/en ...

  5. Docker搭建ELK分析tomat日志

    最近公司的项目中用到了ELK,正好有时间自己搭建一个学习一下.在实体机或虚拟机中搭建还需要安装软件,使用docker镜像安装是省时省力的,如下是步骤. 1. 下载elasticsearch镜像: #d ...

  6. 性能分析 | JVM发生内存溢出的8种原因及解决办法

    推荐阅读:史上最详细JVM与性能优化知识点综合整理 1.Java 堆空间 2.GC 开销超过限制 3.请求的数组大小超过虚拟机限制 4.Perm gen 空间 5.Metaspace 6.无法新建本机 ...

  7. redis2. sds 字符串(SimpleDynamicString)

    1.标准strcat 会有溢出风险,sdscat无溢出风险 2.空间预分配,惰性空间释放 空间预分配:sds分配空间时,如果原来是5,free是0, sdscat追加一个10长度的,此时字符串加长到1 ...

  8. <javaScript>谈谈JavaScript中的变量、指针和引用

    1.变量我们可能产生这样一个疑问:编程语言中的变量到底是什么意思呢?事实上,当我们定义了一个变量a时,就是在存储器中指定了一组存储单元,并将这组存储单元命名为a.变量a的值实际上描述的是这组存储单元中 ...

  9. Cloudera Manager产品介绍

    一.Cloudera Manager简介 Cloudera Manager(后面简称CM)是CDH(Cloudera’s Distribution Including Apache Hadoop)市场 ...

  10. Django学习之缓存和信号

    Django学习之缓存和信号   一 缓存 由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views ...