zoukankan      html  css  js  c++  java
  • Neo4j Cypher语法(一)

    目录

    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 字符串常用的转义序列

    Tab键  后退键 新起一行 回车符 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
  • 相关阅读:
    Ionic Tabs使用
    Angular 4 延缓加载组件
    JSP include 指令
    JSP 执行流程
    Tomcat 配置
    Spring boot 项目创建(Spring Boot 1.5.7 + Spring Data JPA + MySql)
    Java Web Service 学习笔记
    Tomcat 去除项目名称
    Angular 4 路由守卫
    Angular 4 辅助路由
  • 原文地址:https://www.cnblogs.com/jpfss/p/11738650.html
Copyright © 2011-2022 走看看