Neo4j 入门到精通(Cypher语言详解)

什么是Neo4j?

Neo4j是用Java实现的开源NoSQL图数据库。从2003年开始开发,2007年正式发布第一版,其源码托管于GitHtb。Neo4j作为图数据库中的代表产品,已经在众多的行业项目中进行了应用,如:网络管理、软件分析、组织和项目管理、社交项目等方面。

官网 https://neo4j.com/

Neo4j实现了专业数据库级别的图数据模型的存储,提供了完整的数据库特性,包括ACID事务的支持、集群的支持、备份和故障转移等。

Neo4j提供了申明式的查询语言Cypher,它类似于关系型数据库中的SQL语言,其具有表现力丰富、使用简单、查询效率高、高扩展性等特点。

它存储的数据大致是这样的:

版本说明

一般来说分为两个不同的版本,社区版以及企业版

社区版免费,我们主要利用社区办进行下述讲解

部署

你可以直接在官网上下载社区版,我们这边写一下linux的部署 ,安装完docker之后执行下述命令即可

docker run \

-d \

--restart=always \

--name neo4j \

-p 7474:7474 \

-p 7687:7687 \

-v neo4j:/data \

neo4j:4.4.5

体验neo4j

点击按钮

出现这个界面

这个时候点击右下角的next,出现一行代码

点击复制,放到

执行即可

ok现在你已经会了第一步了,接下来我们学习Cypher语句

数据结构

eo4j中采用节点、属性、关系、标签来存储数据。如下:

  • 节点
    • 存储实体数据,在上图中,演员、电影都是节点。
    • 可以理解为关系型数据库中的表。
  • 关系
    • 存储节点之间的关系。
    • 关系只能有一个类型,必须有开始节点和结束节点以及指向。
    • 关系可以自我循环引用,但是两头永远不能为空。
  • 属性

    • 节点和关系都可以有属性,它是由键值对组成的。
    • 节点的属性可以理解为关系型数据库中的字段。
    • 关系中的属性进一步的明确了关系。
  • 标签
    • 标签是对节点的分类,这样使得构建Neo4j数据模型更加简单。
    • 在上面的电影案例中,Movie、Person就是标签

Cypher语言

创建数据

板子

1 查询所有 数据

match (n) return n;

2 删除所有节点和关系,慎用!

match (n) detach delete n

3 创建节点该节点具有name属性,n为该节点名称,返回n ,

create (n {name: $value}) return n

4.创建节点,指定标签

crearte (n:Tag { name : value })

5.创建n指向m的关系 ,并且指定关系类型为 knows

create (n)-[r:KNOWS]->(m)

实例

//示例

CREATE (n {name:'迪士尼营业部'})

CREATE (n:AGENCY {name:'航头营业部'})

//创建浦东新区转运中心、上海转运中心节点,并且创建关系为:IN_LINE,创建完成后返回节点和关系

//TLT -> Two Level Transport(二级转运中心)

//OLT -> One Level Transport(一级转运中心)

CREATE (n:TLT {name:'浦东新区转运中心'}) -[r:IN_LINE]-> (m:OLT {name:'上海转运中心'}) RETURN n,r,m

//关系也是可以反向,并且可以为关系中指定属性

CREATE (n:TLT {name:'浦东新区转运中心'}) <-[r:OUT_LINE]- (m:OLT {name:'上海转运中心'}) RETURN n,r,m

查询

//条件查询

MATCH WHERE

//查询的结果以管道的形式传递给下面的语句,聚合查询必须使用WITH

WITH \[ORDER BY\] \[SKIP\] \[LIMIT\]

//返回、排序、跳过、返回个数

RETURN [ORDER BY] [SKIP] [LIMIT]

好了你现在已经知道了简单的构造和查询语句,接下来我们举个例子

分页查询

分页查询网点,按照bid正序排序,每页查询2条数据,第一页

match (n:AGENCY)

return n order by n.bid ASC skip 0 limit 2 //z这里的skip之后的实际上就是跳过多少页

//第二页

match (n:AGENCY)

return n order by n.bid ASC skip 2 limit 2

更新数据

//查询出来之后进行更新即可

// 更新/设置 属性

match (n:AGENCY {name:"北京市昌平区新龙城"})

set n.address = "龙跃苑四区3号楼底商101号"

return n

//通过remove移除属性

match (n:AGENCY {name:"北京市昌平区新龙城"})

remove n.address RETURN n

//没有address属性的增加属性

match (n:AGENCY) where n.address is null set n.address = "暂无地址"

删除数据

//删除节点

MATCH (n:AGENCY {name:"航头营业部"}) DELETE n

//有关系的节点是不能直接删除的

MATCH (n:AGENCY {name:"北京市昌平区新龙城"}) DELETE n

//删除节点和关系

MATCH (n:AGENCY {name:"北京市昌平区新龙城"}) DETACH DELETE n

//删除所有节点和关系,慎用!

MATCH (n) DETACH DELETE n

案例

建表语句,用作练习

CREATE (北京市转运中心:OLT {bid: 8001, name: "北京市转运中心", address: "北京市转运中心", location : point({latitude:39.904179, longitude:116.407387})})

CREATE (上海市转运中心:OLT {bid: 8002, name: "上海市转运中心", address: "上海市转运中心", location : point({latitude:31.230525, longitude:121.473667})})

CREATE (南京市转运中心:OLT {bid: 8003, name: "南京市转运中心", address: "南京市转运中心", location : point({latitude:32.059344, longitude:118.796624})})

CREATE (太原市转运中心:OLT {bid: 8004, name: "太原市转运中心", address: "太原市转运中心", location : point({latitude:37.870451, longitude:112.549656})})

CREATE (郑州市转运中心:OLT {bid: 8005, name: "郑州市转运中心", address: "郑州市转运中心", location : point({latitude:34.745551, longitude:113.624321})})

CREATE

(北京市转运中心)-[:IN_LINE {cost:10684.9}]->(上海市转运中心),

(北京市转运中心)<-[:OUT_LINE {cost:10684.9}]-(上海市转运中心),

(北京市转运中心)-[:IN_LINE {cost:8993.1}]->(南京市转运中心),

(北京市转运中心)<-[:OUT_LINE {cost:8993.1}]-(南京市转运中心),

(南京市转运中心)-[:IN_LINE {cost:2699.4}]->(上海市转运中心),

(南京市转运中心)<-[:OUT_LINE {cost:2699.4}]-(上海市转运中心),

(太原市转运中心)-[:IN_LINE {cost:3609.7}]->(郑州市转运中心),

(太原市转运中心)<-[:OUT_LINE {cost:3609.7}]-(郑州市转运中心),

(郑州市转运中心)-[:IN_LINE {cost:5659.7}]->(南京市转运中心),

(郑州市转运中心)<-[:OUT_LINE {cost:5659.7}]-(南京市转运中心)

CREATE (昌平区转运中心:TLT {bid: 90001, name: "昌平区转运中心", address: "昌平区转运中心", location : point({latitude:40.220952, longitude:116.231034})})

CREATE (北京市昌平区新龙城:AGENCY {bid: 100260, name: "北京市昌平区新龙城", address: "龙跃苑四区3号楼底商", phone : "010-53049073,010-53576707", location : point({latitude:40.07544443596149, longitude:116.3470535709328})})

CREATE

(北京市昌平区新龙城)-[:IN_LINE {cost:189.7}]->(昌平区转运中心),

(北京市昌平区新龙城)<-[:OUT_LINE {cost:189.7}]-(昌平区转运中心)

CREATE (北京市昌平区定泗路:AGENCY {bid: 100280, name: "北京市昌平区定泗路", address: "北七家镇定泗路苍龙街交叉口", phone : "010-86392987", location : point({latitude:40.11765281246394, longitude:116.37212849638287})})

CREATE

(北京市昌平区定泗路)-[:IN_LINE {cost:166.2}]->(昌平区转运中心),

(北京市昌平区定泗路)<-[:OUT_LINE {cost:166.2}]-(昌平区转运中心)

CREATE (海淀区转运中心:TLT {bid: 90002, name: "海淀区转运中心", address: "海淀区转运中心", location : point({latitude:39.959893, longitude:116.2977})})

CREATE (北京市海淀区小营:AGENCY {bid: 100347, name: "北京市海淀区小营", address: "北京市昌平区回龙观街道金燕龙大厦停车场", phone : "010-86483817,010-86483817,010-86483817", location : point({latitude:40.06177798692319, longitude:116.32706587559049})})

CREATE

(北京市海淀区小营)-[:IN_LINE {cost:116.1}]->(海淀区转运中心),

(北京市海淀区小营)<-[:OUT_LINE {cost:116.1}]-(海淀区转运中心)

CREATE (北京市海淀区万泉河:AGENCY {bid: 100227, name: "北京市海淀区万泉河", address: "北京市海淀区四季青镇杏石口路47号院", phone : "18521852356", location : point({latitude:39.94882822425318, longitude:116.25707017441161})})

CREATE

(北京市海淀区万泉河)-[:IN_LINE {cost:36.8}]->(海淀区转运中心),

(北京市海淀区万泉河)<-[:OUT_LINE {cost:36.8}]-(海淀区转运中心)

CREATE

(昌平区转运中心)-[:IN_LINE {cost:383.3}]->(北京市转运中心),

(昌平区转运中心)<-[:OUT_LINE {cost:383.3}]-(北京市转运中心),

(海淀区转运中心)-[:IN_LINE {cost:112.3}]->(北京市转运中心),

(海淀区转运中心)<-[:OUT_LINE {cost:112.3}]-(北京市转运中心)

CREATE (浦东新区转运中心:TLT {bid: 90003, name: "浦东新区转运中心", address: "浦东新区转运中心", location : point({latitude:31.221461, longitude:121.544346})})

CREATE (上海市浦东新区南汇:AGENCY {bid: 210057, name: "上海市浦东新区南汇", address: "园春路8号", phone : "18821179169", location : point({latitude:31.035240152911637, longitude:121.73459966751048})})

CREATE

(上海市浦东新区南汇)-[:IN_LINE {cost:275.4}]->(浦东新区转运中心),

(上海市浦东新区南汇)<-[:OUT_LINE {cost:275.4}]-(浦东新区转运中心)

CREATE (上海市浦东新区周浦:AGENCY {bid: 210127, name: "上海市浦东新区周浦", address: "川周公路3278-8号", phone : "021-68060322", location : point({latitude:31.132409729356993, longitude:121.59815370294322})})

CREATE

(上海市浦东新区周浦)-[:IN_LINE {cost:111.6}]->(浦东新区转运中心),

(上海市浦东新区周浦)<-[:OUT_LINE {cost:111.6}]-(浦东新区转运中心)

CREATE (奉贤区转运中心:TLT {bid: 90004, name: "奉贤区转运中心", address: "奉贤区转运中心", location : point({latitude:30.918406, longitude:121.473945})})

CREATE (上海市奉贤区东部:AGENCY {bid: 210017, name: "上海市奉贤区东部", address: "上上海市奉贤区洪庙镇洪兰路351", phone : "021-57171717", location : point({latitude:30.917752751719863, longitude:121.67587819184698})})

CREATE

(上海市奉贤区东部)-[:IN_LINE {cost:192.9}]->(奉贤区转运中心),

(上海市奉贤区东部)<-[:OUT_LINE {cost:192.9}]-(奉贤区转运中心)

CREATE (上海市奉贤区青村:AGENCY {bid: 210442, name: "上海市奉贤区青村", address: "姚家村1127号", phone : "021-57566663,021-57566606", location : point({latitude:30.916946897994983, longitude:121.57954144207972})})

CREATE

(上海市奉贤区青村)-[:IN_LINE {cost:100.9}]->(奉贤区转运中心),

(上海市奉贤区青村)<-[:OUT_LINE {cost:100.9}]-(奉贤区转运中心)

CREATE

(浦东新区转运中心)-[:IN_LINE {cost:68.0}]->(上海市转运中心),

(浦东新区转运中心)<-[:OUT_LINE {cost:68.0}]-(上海市转运中心),

(奉贤区转运中心)-[:IN_LINE {cost:347.4}]->(上海市转运中心),

(奉贤区转运中心)<-[:OUT_LINE {cost:347.4}]-(上海市转运中心)

CREATE (玄武区转运中心:TLT {bid: 90004, name: "玄武区转运中心" , location : point({latitude:32.048644, longitude:118.797779})})

CREATE (江苏省南京市玄武区紫金墨香苑:AGENCY {bid: 25073, name: "江苏省南京市玄武区紫金墨香苑", address: "栖霞区燕尧路100号", phone : "025-58765331,025-83241955,025-83241881", location : point({latitude:32.117016089520305, longitude:118.86319310255513})})

CREATE

(江苏省南京市玄武区紫金墨香苑)-[:IN_LINE {cost:98.0}]->(玄武区转运中心),

(江苏省南京市玄武区紫金墨香苑)<-[:OUT_LINE {cost:98.0}]-(玄武区转运中心)

CREATE (江苏省南京市玄武区长江路:AGENCY {bid: 25023, name: "江苏省南京市玄武区长江路", address: "观音阁10号", phone : "18521133265,18695799166", location : point({latitude:32.04803554410631, longitude:118.79190455263355})})

CREATE

(江苏省南京市玄武区长江路)-[:IN_LINE {cost:5.6}]->(玄武区转运中心),

(江苏省南京市玄武区长江路)<-[:OUT_LINE {cost:5.6}]-(玄武区转运中心)

CREATE

(玄武区转运中心)-[:IN_LINE {cost:12.0}]->(南京市转运中心),

(玄武区转运中心)<-[:OUT_LINE {cost:12.0}]-(南京市转运中心)

CREATE (小店区转运中心:TLT {bid: 90005, name: "小店区转运中心" , location : point({latitude:37.736865, longitude:112.565524})})

CREATE (山西省太原市青龙:AGENCY {bid: 351068, name: "山西省太原市青龙", address: "长治路33号经典家园停车场内13号商铺", phone : "0351-2025888", location : point({latitude:37.83589608758359, longitude:112.56059258109424})})

CREATE

(山西省太原市青龙)-[:IN_LINE {cost:110.3}]->(小店区转运中心),

(山西省太原市青龙)<-[:OUT_LINE {cost:110.3}]-(小店区转运中心)

CREATE (山西省太原市长风街:AGENCY {bid: 351045, name: "山西省太原市长风街", address: "平阳路104号省农机公司院内", phone : "18636100730", location : point({latitude:37.809964384001226, longitude:112.55299317699505})})

CREATE

(山西省太原市长风街)-[:IN_LINE {cost:82.1}]->(小店区转运中心),

(山西省太原市长风街)<-[:OUT_LINE {cost:82.1}]-(小店区转运中心)

CREATE

(小店区转运中心)-[:IN_LINE {cost:149.4}]->(太原市转运中心),

(小店区转运中心)<-[:OUT_LINE {cost:149.4}]-(太原市转运中心)

CREATE (中原区转运中心:TLT {bid: 90006, name: "中原区转运中心" , location : point({latitude:34.74828, longitude:113.612966})})

CREATE (河南省郑州市郑上路:AGENCY {bid: 371067, name: "河南省郑州市郑上路", address: "中原西路西四环西北角", phone : "0371-55116757,0371-68014786", location : point({latitude:34.74753024533005, longitude:113.57428550005442})})

CREATE

(河南省郑州市郑上路)-[:IN_LINE {cost:35.4}]->(中原区转运中心),

(河南省郑州市郑上路)<-[:OUT_LINE {cost:35.4}]-(中原区转运中心)

CREATE (河南省郑州市颍河路:AGENCY {bid: 371086, name: "河南省郑州市颍河路", address: "航海西路与西三环交叉口向南300米路西中贸商务", phone : "19139415556", location : point({latitude:34.71593280680163, longitude:113.60398506929064})})

CREATE

(河南省郑州市颍河路)-[:IN_LINE {cost:36.9}]->(中原区转运中心),

(河南省郑州市颍河路)<-[:OUT_LINE {cost:36.9}]-(中原区转运中心)

CREATE

(中原区转运中心)-[:IN_LINE {cost:11.5}]->(郑州市转运中心),

(中原区转运中心)<-[:OUT_LINE {cost:11.5}]-(郑州市转运中心)

基本查询

//查询所有的数据

match (n) return n;

//查询所有的网点

match (n:AGENCY)return n //查询的时候加上标签即即可

//查询所有与北京市相关的

match (n:OLT {name: "北京市转运中心"}) -- (m) return n,m //双向边就不需要带上剪头了

//查询所有"北京市转运中心"关联的一级转运中心

match (n:OLT {name:"北京市转运中心"}) --> (m:OLT) return n,m

//将查询赋值与变量

match p = (n:OLT {name:"北京市转运中心"}) --> (m:OLT) return p

关系深度查询

这个也是neo4j中最最重要的属性,可以直接显示两点之间的一个道路,已经自定义最近的道路

语法格式 -[:TYPE*minHops..maxHops]->

//查询【北京市转运中心】关系中深度为1~2层关系的节点

match (n:OLT {name:"北京市转运中心"}) -[*1..2]->(m) return *

//也可以这样

match (n:OLT {name:"北京市转运中心"}) -[*..2]->(m) return * //默认从1开始,注意你想要2..3是不可以的

//也可以通过变量的方式查询

match path = (n:OLT {name:"北京市转运中心"}) -[*..2]->(m)

return path

//查询关系,relationships()获取结果中的关系,WITH向后传递数据

match path = (n:OLT {name:"北京市转运中心"}) -[*..2]->(m)

with n,m, relationships(path) AS r

return r

//注意上述这个查询仅仅返回数据

//查询两个网点之间所有的路线,最大深度为6,可以查询到2条路线

match path = (n:AGENCY) -[*..6]->(m:AGENCY)

where n.name = "北京市昌平区定泗路" AND m.name = "上海市浦东新区南汇"

return path

//查询两个网点之间最短路径,查询深度最大为10

match path = shortestPath((n:AGENCY) -[*..10]->(m:AGENCY))

where n.name = "北京市昌平区定泗路" AND m.name = "上海市浦东新区南汇"

return path

//最短路径我们如果调用shortestPath的话,实际上求得是最短的长度路径的多少

//查询两个网点之间所有的路线中成本最低的路线,最大深度为10(如果成本相同,转运节点最少)

match path = (n:AGENCY) -[*..10]->(m:AGENCY)

where n.name = "北京市昌平区定泗路" AND m.name = "上海市浦东新区南汇"

unwind relationships(path) AS r

with sum(r.cost) AS cost, path

return path ORDER BY cost ASC, LENGTH(path) ASC LIMIT 1

//UNWIND是将列表数据展开操作

//sum()是聚合统计函数,类似还有:avg()、max()、min()等

当然,spring中已经集成,也就是spring data neo4j ,但是对于上述操作我认为还是需要了解并且知道的

与关系型数据库的对比

特性 Neo4j(图数据库) MySQL(关系型数据库)
数据模型 原生图结构(节点+关系+属性) 表结构(行+列)
存储结构 专用的图存储文件(节点、关系独立存储) B+树索引 + 行存储
查询语言 Cypher(声明式图查询) SQL(基于集合的操作)
连接查询 天然高效(直接遍历关系) 需要 JOIN 操作,性能随数据量增长下降
适用场景 社交网络、推荐系统、知识图谱 事务处理、结构化数据存储

总结

  • Neo4j 底层数据结构
    • 节点:固定大小记录,存储 ID、标签和属性。
    • 关系:固定大小记录,存储 ID、起始/结束节点、类型和属性。
    • 属性:键值对存储为压缩的二进制格式,通过字典和索引加速访问。
  • 存储引擎:原生图存储,文件与内存缓存结合,优化图遍历性能。
  • 索引:支持标签、关系类型、属性等多种索引,加速查询。

Neo4j 的底层设计使其成为 ​处理复杂关系数据的高性能解决方案,尤其适合需要频繁遍历节点和关系的场景(如社交网络分析、欺诈检测等)。 🚀

相关推荐
喜欢打篮球的普通人2 天前
MLIR快速入门
neo4j·mlir
ELI_He9992 天前
Neo4j 安装 APOC
neo4j
綮地3 天前
Neo4j 基本处理
neo4j
lzp07913 天前
Neo4j图数据库学习(二)——SpringBoot整合Neo4j
数据库·学习·neo4j
爱折腾的小码农3 天前
neo4j数据库桌面管理工具
数据库·neo4j
Wenhao.7 天前
Docker 安装 neo4j
docker·容器·neo4j
RDCJM8 天前
Neo4j图数据库学习(二)——SpringBoot整合Neo4j
数据库·学习·neo4j
机器不学习我也不学习10 天前
TensorFlow环境安装
neo4j
码农老李11 天前
vxWorks7.0 Simpc运行tensorflow lite example
人工智能·tensorflow·neo4j
小鸡吃米…1 个月前
TensorFlow 实现异或(XOR)运算
人工智能·python·tensorflow·neo4j