美文网首页python
Cypher学习笔记

Cypher学习笔记

作者: yangOvOyang | 来源:发表于2018-01-05 20:55 被阅读19次

    Neo4j的Cypher语言具有以下特点:

    • 声明性模式匹配语言
    • 遵循SQL语法
    • 语法非常简单并且人性化、可读的格式

    第一章 基础

    注释

    注释符 //

    参数

    Cypher支持带参数的查询,这样就不必必须使用字符串来构建查询了。
    举个简单的例子:

    match (a) where a.name = $name return n
    

    等价于

    match (a {name: $name})
    

    $name可以通过所使用的驱动来提交上去。

    运算符

    • 数学运算符
      +、-、*、/、%、^
    • 比较运算符(同时支持链式比较)请记住没有==
      =、<>、<、>、<=、>=、is null、is not null
    • 布尔运算符
      and、or、xor、not
    • 字符串运算符
      +、=~
    • 列表运算符
      +、in
    • 属性运算符 (已删除)
      ?、!

    第二章 模式

    模式和模式匹配是Cypher的操作对象。相当于在白板上画出图的形状,模式在match、create和merge等语句后出现。

    • 节点模式
      最简单的表达,(a)或者()
    • 关系节点的模式
      后续不需要使用节点时,可以不给变量名 (a)-->(b)或者(a)-->()
    • 描述关系
      (1)如果不关心关系的方向的时候,箭头可以省略,如 (a)--(b)或者 (a)-->(b)
      (2)如果后续需要使用关系,可以给关系起个变量名,如 (a)-[r]->(b)
      (3)在查询已经存在的数据的时候,如果关系的类型可以是一个类型集中的任意一种,可以用 | 间隔,如 (a)-[r:TYPE1|TYPE2]-(b)
      (4)描述路径的长度,左右边界二者可任缺,并且也可以限制路径的类型,如 (a)-[*2]->(b) 或者 (a)-[:is_a*3..5]->(b) 或者 (a)-[*3..]->(b) 或者 (a)-[*..5]->(b) 或者 (a)-[*]->(b)

    第三章 列表

    列表基本操作

    //列表
    [0,1,2,3,4,5]
    //生成0到10的列表(和python不一样)
    range(0,10)
    //取列表某个元素
    range(0,10)[3] //取值
    range(0,10)[-3] //反向取值
    range(0,10)[0..3] //切片,左右索引可缺省,类似python
    //size()获取列表长度
    size(range(0,10)[0..3])
    

    列表生成式

    return [x in range(0,10) where x%2 = 0 | x^3] as result
    

    运行结果是


    运行结果

    create 命令

    (1) 创建节点和属性数据

    //创建一个单标签结点
    create (p:Person{name:'Owen',age:23})  //注意这里的p只是创建节点的一个临时的变量名,毫无意义  
    
    //创建一个多标签的节点
    create (p:Person:Student)
    

    (2) 创建关系

    直接创建关系

    create (a:Person{name:'周杰伦'})-[r:妻子]->(b:Person{name:'昆凌'})  return a,b,r
    

    在已有节点上创建关系

    match (a:Person),(b:Person) where a.name = '昆凌' and b.name = '周杰伦' create (a)-[c:嫁给了]->(b) return a,b
    

    match-return 命令

    (1) 查找有关节点和属性数据

    //查找所有Person标签的节点
    match (p:Person) return p
    
    //查找所有Person标签的节点的姓名
    match (p:Person) return p.name
    

    (2) 查找关系

    match (a)-[r]->(b) return a,b,r
    

    where 命令

    用法和SQL一样,很简单,起到过滤的作用

    match (p:Person) where p.name = 'Owen' return p
    match (p:Person) where not p.name = 'Owen' return p
    match (p:Person) where p.name = 'Owen' return distinct p
    

    with 命令

    with命令和return命令很相似,区别是with语句并不是完成查询,而是为后面的部分准备输入

    //collect()将所有满足值聚集在一个列表中
    match (p:Person)-[:ACTED_IN]->(m:Movie)
    with p, count(*) as appearances, collect(m.title) as movies
    where appearances > 1
    return p.name, appearances, movies
    
    delete 和 remove 命令
    • delete是删除节点或者关系
    • remove是移除节点或者关系的属性、标签
    //删除节点
    match (p:Person) where p.age<30 delete p
    
    //删除节点及其之间的关系
    match (a:Star{name:'周杰伦'})-[r]->(b:Model{name:'昆凌'})
    delete a,b,r
    return a,b,r
    
    //删除某个节点的某个属性
    match (a:Person) remove a.name return a
    
    set 命令

    添加或者修改节点或者关系的属性,和remove反过来

    //给节点增加属性
    match (a:Person{name:'李伟'}) set a.englishname = 'Li Wei' return a
    
    order by 命令

    用于排序,默认升序,使用desc改为降序

    //按照升序
    match (s:Student) return s.name, s.score order by s.score
    

    接下来的命令,使用下数据:

    create (n:Person{name:'付洋', age:23, school:'wust'}),
    (m:Person{name:'夏林旭', age:25, school:'wust'}),
    (p:Worker{name:'付洋', age:23, dept:'IT'}),
    (q:Worker{name:'李伟', age:30, dept:'产品经理'}),
    (s:Worker{name:'夏林旭', age:25, dept:'产品经理'})
    
    union 和 union all 命令

    将两个结果集合并,要求列名一致,列的数据类型一样
    另外,as可以给列起别名。

    //方法一
    match (m:Person) return m.name as name, m.age as age
    union
    match (n:Worker) return n.name as name, n.age as age
    
    //方法二
    match (m:Person) return m.name, m.age
    union
    match (m:Worker) return m.name, m.age
    
    //错误方法
    match (m:Person) return m.name, m.age
    union
    match (n:Worker) return n.name, n.age
    //解释:return后面的变量名就是列名,所以m.name和n.name不一样,union必须保证列名一样,数据类型一样
    

    那么对于一个不存在的列名,比如Worker不存在school属性,那么就会返回null

    match (m:Person) return m.name, m.age, m.school
    union
    match (m:Worker) return m.name, m.age, m.school
    
    运行结果

    另外,看一下union all的使用方法,只需要对比

    match (m:Person) return m.name
    union all
    match (m:Worker) return m.name
    
    match (m:Person) return m.name
    union
    match (m:Worker) return m.name
    
    union all的运行结果
    union的运行结果

    就可以看出来,union all不具备过滤重复行的功能,它是返回两个结果集所有行,并形成一个单一的结果集。

    limit 和 skip

    还记得sql语句中的limit使用方法吗,两种使用方法分别是limit 23limit 0, 23,但是在NoSQL中就只有第一种了。
    和limit的顺序相反,skip是从底部计数的

    merge 合并 = create + match

    相当于如果图中存在就直接返回,没有就创建并返回

    merge (q:Worker{name:'夏林旭', age:25, dept:'产品经理'}) return q
    merge (q:Worker{name:'张真练', age:25, dept:'产品经理'}) return q
    merge (q:Worker{name:'夏林旭', age:25, dept:'产品经理'}) return q
    
    //merge允许添加额外的属性
    merge (m:Movie {title:'Cloud Atlas'})
    on create set m.released = 2012
    return m
    

    总结一下,merge用于向图中添加东西是很安全的,不用检查是否已经存在

    in

    id是节点和关系默认的内部属性,每创建一个节点或者关系,服务器都将为内部使用分配一个数字,并且自动递增。节点和关系是分开的两套id

    CAPTION 标题

    显示图的时候,显示出来的属性对应着CAPTION,如果CAPTION为name,那么就显示name

    关系

    neo4j只支持创建单向的关系,而且必须有方向。但是在查询时可以不带方向。

    //创建的时候必须单向
    create (a)-[]->(b)
    //查询的时候无视方向
    match (a)-[]-(b) return a,b
    

    关系的数量

    (a)-[*2]->(b) //长度为2
    (a)-[*3..5]->(b) //长度最小3,最大5
    

    函数篇

    字符串函数

    字符串函数有四个,分别是LOWER(), UPPER(), SUBSTRING(), REPLACE()

    match (a:Person) return UPPER(a.school), LOWER(a.school), SUBSTRING(a.school, 0, 1), REPLACE(a.school, 'w', 'BBB')
    

    很简单,运行结果就不贴图了

    聚合函数 aggregation

    个人理解,就是一些功能性的函数,可以通过return返回

    match (p:Worker) return count(*)
    match (p:Worker) return max(p.age), min(p.age), avg(p.age), sum(p.age)
    

    也很简单,一看就懂,略过

    关系函数

    startnode(), endnode()

    create (p:Star{name:'周杰伦'})-[r:marry]->(q:Model{name:'昆凌'})
    match (a)-[r]->(b) return startnode(r).name, endnode(r).name, id(r), type(r)
    
    运行结果
    unique 约束
    //添加unique约束
    create constraint on (p:Person) assert p.name is unique
    //消除unique约束
    drop constraint on (p:Person) assert p.name is unique
    
    特殊操作符?和!
    //如果没有name属性,直接返回true
    where p.name ? = 'foo'
    //如果没有name属性,直接返回false
    where p.name!= ‘foo’
    
    正则表达式~=
    //返回名字以a开头的人
    match (p:Person) where p.name ~= 'a.*'
    
    case表达式

    case表达式相当于if-else分支语句
    准备三个城市节点:湖北武汉,湖北黄石,以及浙江杭州。

    //节点特定的某个属性做分支操作:湖北省的节点,直接返回城市名,其余省的城市返回省名+城市名
    match (city)
    return 
        case city.province
            when '湖北' 
                then city.name
            else 
                city.province + '-' + city.name
        end
    as result
    
    运行结果
    //对节点的任意属性分别做判断
    match (city)
    return city.name,
        case
            when city.name = '武汉'
                then '太好了,是武汉'
            when city.province = '湖北'
                then '好歹也是湖北'
            else
                '什么也不是'
        end
    as result
    
    image.png
    Cypher示例
    //查找和Tom Hanks同出演过电影的人
    match (tom:Person {name:'Tom Hanks'})-[:ACTED_IN]->(m)<-[:ACTED_IN]-(CoActor) return CoActor
    
    //查找与Kevin Bacon存在4条以内关系的任何演员和电影
    match (bacon:Person {name:'Kevin Bacon'})-[*1..4]-(hollywood)  return distinct hollywood
    
    //查找两个节点之间的最短关系路径
    match p = shortestPath((bacon:Person{name:'Kevin Bacon'})-[*]-(meg:Person{name:'Meg Ryan'})) return p
    
    //清空数据库
    match (a:Person), (m:Movie) optional match (a)-[r1]-(), (m)-[r2]-() delete a,r1,m,r2
    

    一朝立志,日夜前行,志同道合者敬请不吝赐教。

    相关文章

      网友评论

        本文标题:Cypher学习笔记

        本文链接:https://www.haomeiwen.com/subject/xlasnxtx.html