Cypher我理解是一种联系操作语言,之所以将其称为“联系”就是要使之和传统SQL数据库的“关系”相区分。操作对象即图数据库独有的节点(Nodes)、标签(Labels)、联系(Relationships)和属性(Properties)。解释一下,以便理解的更为深入:
- Node:表征实体,如:人、公司、账户或其他类似的东西。
- Label:标签不是一开始就有的,后续更新的版本加入了这个功能,极为好用。因为人脑的两种基本认知方式之一就是分类,而标签就是最佳的方法。标签用于标识Node的类别,一个节点可拥有一个或多个标签。标签有助于创建索引,加速检索。
- Relationship:联系定义了两个Node之间的连接。联系还可以有自己的属性和方向。
- Property:用于存储Node的相关信息,是Node的内涵定义。属性可以被Node和Relationship拥有,一如Node一样,Property也是一种广泛而基本的存在。
- 首先,进行语法解析、正确性检查、产生执行计划;
- 其次,定位至初始节点;
- 再次,选择和遍历联系;
- 最后,更改或返回值。
一、基本语法(CURD):
1. Create
试着创建一个Node,这个节点是一个人--顾双双,是我心理咨询的一个来访者,性别女,年龄23。仿照基本格式先写一个:
- create (顾双双:患者{gender:"女",age:"23"})
当然了,这和我的本意并不相符,我是打算创建姓名为“顾双双”的患者,希望姓名可以在Node中心显示出来。所以,现在CREATE的格式是:create (?:标签名{属性名1:"属性1值",属性名2:"属性2值"}),所以现在主要的问题是弄清楚“?”代表什么,或者这个部分是否可以省略。
弄清楚了:?代表的是创建的本实例,正规的一个格式是:
- create (n:患者{gender:"女",age:23})
好了,另一个与Create齐名的语法也必须介绍了,这就是:merge,非常非常重要。Merge好似if-else语句,基本逻辑是先检测merge后面的条件,看看有没有匹配的返回值,如果有则执行on merge分支,如果没有则走on create。逻辑很简单,humane:看是否需要merge,找到的话就合并,没找到就新建。
首先,merge条件部分可以单独执行,不过意义不大:
还是用例子说明:
- merge (x:患者{gender:"男"})
- on match set x.name = "小明", x.birthday = 2007/06/02
- on create set x.created_time = timestamp()
但年龄还是有问题:
到stackOverFlow上找了一下,都说需要手工将时间转成timestamp,因为Neo4j只有一个timestamp()函数而且还没有参数,很多人在抱怨这个问题,估计官方日后一定会增强这方面的功能。
执行了如下语句后,激活了On create分支,因为数据库中目前并没有 性别是“P”的患者:
- merge (x:患者{gender:"P"})
- on match set x.name = "小明", x.birthday = "2007/06/02"
- on create set x.created_time = timestamp()
2. Update
更新的操作实际上是由set命令完成的,首先要定位到待修改的节点或联系,然后进行修改。举个例子:
- match (x:患者) where x.gender="男" set x.age=100 return x
3. Retrieve
实际上,查询或检索这一操作是Cypher实际应用中使用次数最频繁的,类似SQL数据库中的SELECT。在Neo4j中,主要是由Match及其后续限定的Where从句构成。
比如,通过如下语句新增一个节点,现在数据库中有一男一女两个节点:
- create (:患者{gender:"男",age:"23"})
- match(x:患者) return x
- match (x:患者) where x.gender="女" return x
还有一个就是Optional Match,其他都一样,差别在于没找到Match不返回任何结果,而Optional Match返回NULL,如下图的“records”所示:
在Match查找前,可以进行定位以加快检索速度和效率。一般而言,Cypher语句以Start开始,每一条查询语句可以有多个起始点(starting points),借助start可以制定Legacy index,虽然这个东东现在已经被schema取代了,但为了后向兼容还是保留了基本功能,如下例所示:
- start n = node:nodesIndx (Gender = "男") return n
- match (x:患者) where x.gender="女" return count(x)
OK,another trick,使用distinct:
- match (x:患者) where x.age="23" return count(distinct x.gender)
查询部分先总结到这儿。
4. Delete
删除任何东西都可以使用Delete,但将上述创建的所有内容一口气删除,不能使用:
- match (n)
- delete n
- match (n)
- detach delete n
但是,还有个好用的东东叫remove,专门用来删除属性和标签,比delete安全一些。比如:
- match (x:患者{gender:"P"}) remove x.created_time return x
5. 总结
之前说Cypher的优化主要是读操作,原因就在于所有操作(Create、Set、Delete或Remove)第一步就是要执行match,而match就是读操作,对特定节点或联系的定位都依赖于读操作。所以,读操作在图数据库中使用的是如此广泛和普遍,以至于成为主要的优化对象一点也不为过。
已经写成长文了,这篇就先到此为止吧。
五岳之巅
2017年5月21日(孟菲斯时间)
11:57
终稿于UM, FIT
2017年5月21日(孟菲斯时间)
11:57
终稿于UM, FIT