【大数据】Neo4j 图数据库使用详解

目录

一、图数据库介绍

[1.1 什么是图数据库](#1.1 什么是图数据库)

[1.2 为什么需要图数据库](#1.2 为什么需要图数据库)

[1.3 图数据库应用领域](#1.3 图数据库应用领域)

二、图数据库Neo4j简介

[2.1 Neo4j特性](#2.1 Neo4j特性)

[2.2 Neo4j优点](#2.2 Neo4j优点)

三、Neo4j数据模型

[3.1 图论基础](#3.1 图论基础)

[3.2 属性图模型](#3.2 属性图模型)

[3.3 Neo4j的构建元素](#3.3 Neo4j的构建元素)

[3.3.1 节点](#3.3.1 节点)

[3.3.2 属性](#3.3.2 属性)

[3.3.3 关系](#3.3.3 关系)

[3.3.4 标签](#3.3.4 标签)

四、Neo4j搭建过程

[4.1 搭建步骤](#4.1 搭建步骤)

[4.1.1 下载镜像](#4.1.1 下载镜像)

[4.1.2 创建目录](#4.1.2 创建目录)

[4.1.3 启动容器](#4.1.3 启动容器)

[4.1.4 访问neo4j web界面](#4.1.4 访问neo4j web界面)

五、Neo4j语法使用

[5.1 数据准备](#5.1 数据准备)

[5.2 Neo4j数据操作命令使用](#5.2 Neo4j数据操作命令使用)

[5.2.1 创建节点](#5.2.1 创建节点)

[5.2.2 创建节点指定标签](#5.2.2 创建节点指定标签)

[5.2.3 创建节点之间的关系](#5.2.3 创建节点之间的关系)

[5.3 查询语法](#5.3 查询语法)

[5.3.1 查询语法](#5.3.1 查询语法)

[5.3.2 基本数据查询](#5.3.2 基本数据查询)

[5.3.3 关系深度查询](#5.3.3 关系深度查询)

[5.3.4 分页查询](#5.3.4 分页查询)

[5.3.5 更新数据](#5.3.5 更新数据)

[5.3.6 删除数据](#5.3.6 删除数据)

[5.4 索引操作](#5.4 索引操作)

[5.4.1 创建索引](#5.4.1 创建索引)

[5.4.2 删除索引](#5.4.2 删除索引)

六、写在最后


一、图数据库介绍

1.1 什么是图数据库

随着社交,电商,金融,零售,物联网等行业的发展,现实社会的关系构成了一张复杂而庞大的关系网,而传统数据库很难处理关系运算,纵然是大数据技术,面临着数据量的不断增长时,在处理数据关系时也会面临算力的瓶颈,因此急需一种支持海量数据关系计算的数据库,图数据库就随之产生了。

1.2 为什么需要图数据库

图数据库是基于图论实现的一种NoSql数据库,其数据存储结构和数据查询方式都是以图论为基础,图数据库主要用于存储更多的连接数据,下图是neo4j官方提供的一张关于电影中演员关系图。

在这样一张关系图谱中,假如要查一下Tom Tykwer这个人与 Frank Darab 两者间的关系,使用关系型数据库来做,估计具有相当的难度。

类似的关系场景还有很多,有些节点上甚至包含了很多属性值,类似这样的应用程序中,数据节点包含了大量的结构化,半结构化,甚至非结构化的连接数据。在传统的RDBMS数据库中,想要表示这种非结构化的连接数据并不简单,如果我们在RDBMS数据库中存储这种连接数据,那么检索或遍历是非常困难,而且性能是非常低效的,所以要表示或存储这种更多需要连接的数据,应该选择一个图数据库来做这件事。

使用图数据库,就能非常容易的存储这种更多需要连接的数据。它将每个配置文件数据作为节点的数据存储在内部,通过与相邻的节点连接,构成关系,这样就形成了关系图谱,检索和遍历也就非常容易且更加高效。

1.3 图数据库应用领域

图数据库在众多的领域有着广泛的使用:

  • 社交领域:用来管理社交关系,实现好友推荐;
  • 零售领域:实现商品实施推荐,为买家提供更好的购物体验;
  • 物流领域:实现对物流网点的精准管理,提供高效便捷的智能物流解决方案;
  • 金融领域:银行业务中可以基于图数据库进行风控的管理;
  • ...

二、图数据库Neo4j简介

Neo4j是⽤Java实现的开源NoSQL图数据库。使用scala和java编写。从2003年开始开发,2007年正式发布第⼀版,其源码托管于GitHtb。Neo4j作为图数据库中的代表产品,已经在众多的⾏业项⽬中进⾏了应⽤,如:⽹络管理、软件分析、组织和项⽬管理、社交项⽬等⽅⾯。

官网:https://neo4j.com

2.1 Neo4j特性

Neo4j具有下面的特点

  • Neo4j实现了专业数据库级别的图数据模型的存储,提供了完整的数据库特性,包括ACID事务的⽀持、集群的⽀持、备份和故障转移等;
  • Neo4j提供了申明式的查询语⾔Cypher,它类似于关系型数据库中的SQL语⾔,其具有表现⼒丰富、使⽤简单、查询效率⾼、⾼扩展性等特点;

Neo4j存储的数据格式如下图展现所示

完整的功能特性总结如下:

  • 提供了查询SQL,即Neo4j CQL,SQL就像简单的查询语言;
  • 它遵循属性图数据模型;
  • 它通过使用Apache Lucence 支持索引;
  • 它支持UNIQUE约束;
  • 它包含一个用于执行SQL的UI界面:Neo4j浏览器;
  • 它支持完整的ACID规则;
  • 它采用原生图形库与本地GPE(图形处理引擎);
  • 它支持查询的数据导出到json和xls格式;
  • 它提供了REST API,可以被任何编程语言访问;
  • 它提供了可以通过任何UI MVC(如node js)访问的java脚本;
  • 它支持两种java api ,cypher api 和native api来访问java应用程序;

2.2 Neo4j优点

综合来说,Neo4j具备如下优点:

  • 它很容易表示连接的数据节点之间的关系;
  • 检索/遍历/导航更多的连接数据简单而且性能高效;
  • 它很容易表示半结构化数据;
  • Neo4j CQL查询语言的命令人性化且可读性高,初学者容易掌握;
  • 数据模型简单而强大;
  • 它无需复杂的连接来检索具有关联关系的数据,因为它很容易检索临近关系的数据节点;

三、Neo4j数据模型

在开始学习neo4j之前,有必要对neo4j的数据模型做一个全面深入的了解,因为在后续操作中,大部分情况下,都是围绕neo4j数据模型中各种概念展开。

3.1 图论基础

图是由表示一组节点和连接这些节点的关系构成,图形以属性的形式将数据存储在节点和关系中,属性用于表示数据的键值对,在图论中,可以用一个带有圆的节点表示,节点之间的关系用一个箭头做标记,最简单的图即单个节点;

比如可以使用节点表示社交网络,单纯的节点无任何属性,比如我们假设这个节点代表社交网络中的某个人,可以向其中填充一些关于这个人的资料信息作为节点属性;

可以用下图表示两个节点之间的关系,在此处,两个配置文件之间的关系为跟随 "Follows",从关系上来说,Node1 遵循 Node2;

3.2 属性图模型

Neo4j图数据库遵循属性图模型来存储和管理数据,属性图模型规则如下:

  • 表示节点,关系和属性中的数据;
  • 节点和关系都包含属性;
  • 关系连接节点;
  • 属性是键值对;
  • 节点用一个圆圈表示,关系用方向键(图中表示箭头)表示;
  • 关系具有方向,单向或双向;
  • 每个关系包含"开始节点"或"从节点",和"到节点"或"结束节点";

在属性图数据模型中,关系应该是定向的,如果我们尝试创建没有方向的关系,它将会抛出一个错误消息,在Neo4j中,关系也应该是具有方向性的。如果我们尝试创建没有方向的关系,N4o4j会抛出一个错误消息,"关系应该是有方向性的"。

Neo4j图数据库将所有数据存储在节点和关系中,所以我们不需要任何额外的RDBMS数据库或NoSql数据库来存储Neo4j数据库数据,它以图的形式存储数据,Neo4j采用本机GPE(图形处理引擎),来使用它的本机图存储格式。

图数据库数据模型的主要模块包括:

  • 节点;
  • 关系;
  • 属性;

下图是一张简单的关系图

在上图中,使用圆圈表示节点,使用箭头表示关系,关系是具有方向性的,而节点中的属性,通常使用键值对(key/value)表示。

3.3 Neo4j的构建元素

Neo4j图数据库主要由以下元素构成:

  • 节点;
  • 属性;
  • 关系;
  • 标签;
  • 数据浏览器;

如下图所示,假如Person代表节点,下图表示两个Person之间的关系

3.3.1 节点

节点(Node)是图数据库中最基本的元素,用来表示一个实体记录,就像关系数据库库中的一条数据,在Neo4j中,一个节点可以包含多个属性和多个标签(label)。

  • 节点是主要的数据元素;
  • 节点通过关系连接到其他节点;
  • 节点可以具有一个或多个属性(即存储为键值对的属性);
  • 节点有一个或多个标签,用于描述在图表中的作用;

3.3.2 属性

属性是用于描述图节点和关系的键值对,其中key为一个字符串,值可以通过使用N4o4j中支持的数据类型来表示

  • 属性是命名值,其中名称(键)是字符串;
  • 属性可以被索引和约束;
  • 可以从多个属性创建复合索引;

3.3.3 关系

关系同样也是图数据库中的基本元素,当数据库中节点已经存在时,需要将节点连接起来构成图,关系就是用以连接两个节点,关系也称为图论的边,其始端和末端必须是节点,关系不能指向空也不能从空发起,关系和节点一样可以包含多个属性,但关系只能有一个类型。

  • 关系连接两个节点;
  • 关系是具有方向性的;
  • 节点可以具有多个关系甚至递归关系;
  • 关系也可以具有一个或多个属性(存储为键值对);

基于方向性,Neo4j关系主要有两种类型:

  • 单向关系;
  • 双向关系;

3.3.4 标签

标签(Label)将一个公共名称与一组节点或关系相关联,节点或关系可以包含一个或多个标签,我们可以为现有的节点或关系创建新标签,也可以从现有节点或关系中删除标签。

  • 标签用于将节点分组;
  • 一个节点可以具有多个标签;
  • 对标签进行索引可以加速在图中的查找效率;
  • 本机标签索引针对速度进行了优化;

四、Neo4j搭建过程

Neo4j支持众多平台的部署安装,如:Windows、Mac、Linux等系统。Neo4j是基于Java平台的,所以部署安装前,先保证已经安装了Java虚拟机。为演示方便,我们使用docker部署Neo4j。

4.1 搭建步骤

按照下面的步骤搭建其Neo4j的环境。

4.1.1 下载镜像

bash 复制代码
docker pull neo4j:4.4.5

4.1.2 创建目录

创建相关的目录,如数据目录,配置文件目录等,作为与容器的映射,在usr/local下创建一个neo4j的目录,然后在neo4j目录下分别创建data、logs、conf、import 四个目录

data------数据存放的文件夹

logs------运行的日志文件夹

conf------数据库配置文件夹

import------为了大批量导入csv来构建数据库,只能导入.csv格式的文件,要放到这个文件夹下)

4.1.3 启动容器

使用下面的命令启动neo4j容器

bash 复制代码
docker run -d --name neo4j_self \
-p 7474:7474 -p 7687:7687 \
-v /usr/local/neo4j/data:/data \
-v /usr/local/neo4j/logs:/logs \
-v /usr/local/neo4j/conf:/var/lib/neo4j/conf \
-v /usr/local/neo4j/import:/var/lib/neo4j/import \
docker.io/neo4j:4.4.5

4.1.4 访问neo4j web界面

容器正常启动之后,输入本机地址加上端口号即可打开neo4j浏览器,如果是云服务器,需要提前开放上面的两个端口,如下:

默认情况下,首次登录账户/密码为,neo4j/neo4j,登录成功后,将跳转到下面的界面提示你修改密码;

密码修改完成后,来到下面的界面就可以开始使用neo4j的可视化界面进行操作了。

五、Neo4j语法使用

5.1 数据准备

紧接着上述访问的web浏览器界面,点击中间的 Open guide,可以导入官方提供的测试数据;

到了第二步时,点击一下左侧区域的数据,在右侧将会看到类似于创建数据库那样的语句,这就是生成的创建测试数据的;

点击右上角的执行按钮,导入成功后,就能看到生成可视化图数据了。

5.2 Neo4j数据操作命令使用

Cypher是Neo4j查询语言,类似与关系型数据库中的SQL,一些关键词来源于SQL,比如:CREATE、WHERE、RETRUN等,官方文档:MATCH - Cypher Manual,下面以上述导入的测试数据为例来练习使用常用的Neo4j操作命令。

5.2.1 创建节点

创建节点,该节点具备name属性,n为该节点的变量,创建完成后返回该节点,语法如下

bash 复制代码
CREATE (n {name: $value}) RETURN n

比如我们创建一个营业网点

CREATE (n {name:'杭州拱墅营业部'})

创建完成后,使用查询命令,可以看到这个数据,当然目前是一个孤立的数据节点;

左侧也可以切换不同的查看维度,比如以json形式展示如下,包含一个属性,但是没有标签;

5.2.2 创建节点指定标签

在上文谈到节点通常带有标签信息,可以通过下面的语句为创建的节点指定标签

bash 复制代码
CREATE (n:$Tag {name: $value}) 

比如,指定这个节点的标签为middle,然后再次执行

CREATE (n:middle {name:'杭州西湖营业部'})

查看其详细信息,可以看到当前的数据中还包含了标签middle信息

5.2.3 创建节点之间的关系

语法

bash 复制代码
#创建n指向m的关系,并且指定关系类型为:KNOWS,r后紧跟着的就是关系名称
CREATE (n)-[r:KNOWS]->(m)  

示例需求:创建两个银行网点,一级银行网点与二级网点,语句如下;

CREATE (n:first_level {name:'杭州银行总部'}) -[r:manager]-> (m:second_level {name:'杭州银行西湖营业部'}) RETURN n,r,m

执行上述语句,看到下面的效果

5.3 查询语法

查询可以说是日常工作中使用最多也最高频的语法,为了全方位练习查询相关的语法,先准备以下模拟测试数据,该数据为一组物流转运的测试数据;

sql 复制代码
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}]-(郑州市转运中心)

执行完成之后,使用查询语句看到如下效果,不同的节点颜色说明是不同的标签,在数据中都有具体的呈现;

5.3.1 查询语法

Cypher查询语法如下:

bash 复制代码
[MATCH WHERE]  //条件查询
[WITH [ORDER BY] [SKIP] [LIMIT]] //查询的结果以管道的形式传递给下面的语句,聚合查询必须使用WITH
RETURN [ORDER BY] [SKIP] [LIMIT] //返回、排序、跳过、返回个数

看到这个有没有觉得与mysql的查询语句有相似的地方

5.3.2 基本数据查询

查询所有数据(数据量大时慎用)

MATCH (n) RETURN n

查询所有标签数据,在上述数据中,标签为物流网点数据

MATCH (n:AGENCY) RETURN n //查询所有网点(AGENCY)

查询所有与"北京市转运中心"有关系的节点

bash 复制代码
MATCH (n:OLT {name: "北京市转运中心"}) -- (m) RETURN n,m

语法说明:

  • OLT,转运中心对应的标签名;
  • name,节点名称;
  • -- ,表示关系,没有箭头指向表示所有与查询节点有关系的数据均返回;

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

bash 复制代码
MATCH (n:OLT {name:"北京市转运中心"}) --> (m:OLT) RETURN n,m

指定关系标签查询,查询关系中指定关系名称为:IN_LINE

bash 复制代码
MATCH (n:OLT {name:"北京市转运中心"}) -[r:IN_LINE]- (m) RETURN n,r,m

查询赋值与变量

可以将查询到的结果赋值给一个变量,方便后续更多的业务逻辑处理;

bash 复制代码
MATCH p = (n:OLT {name:"北京市转运中心"}) --> (m:OLT) RETURN p

通过 type()函数查询关系类型

通过下面的sql返回两个转运中心的关系

bash 复制代码
MATCH (n:OLT {name:"北京市转运中心"}) -[r]-> (m:OLT {name:"南京市转运中心"}) RETURN type(r)

5.3.3 关系深度查询

可以指定关系的深度进行查询,语法格式:-[:TYPE*minHops..maxHops]->,在实际业务中,经常会碰到诸如挖掘节点某个维度或指标的深度,在类似的场景下,就需要使用关系深度查询的语法。

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

下面3种语法都可以

bash 复制代码
#语法1
MATCH (n:OLT {name:"北京市转运中心"}) -[*1..2]->(m) RETURN *
#语法2
MATCH (n:OLT {name:"北京市转运中心"}) -[*..2]->(m) RETURN *
#语法3
MATCH path = (n:OLT {name:"北京市转运中心"}) -[*..2]->(m)
RETURN path

简单来说,以"北京市转运中心"为中心,查询的效果来看与之有一个或两个点长度对应的关系数据都将会返回;

查询节点关系数据

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

bash 复制代码
MATCH path = (n:OLT {name:"北京市转运中心"}) -[*..2]->(m)
WITH n,m, relationships(path) AS r
RETURN r

返回的是关系结果集,通过with函数,可以对上一步得到的查询结果进一步筛选、过滤或处理,从而只返回预期的结果;

查询两个网点之间所有的路线,最大深度为6

可以查询到2条路线,其中where即指定具体的筛选条件,就像mysql中指定具体的字段值等于某个数;

bash 复制代码
MATCH path = (n:AGENCY) -[*..6]->(m:AGENCY)
WHERE n.name = "北京市昌平区定泗路" AND m.name = "上海市浦东新区南汇"
RETURN path

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

注意这里使用了函数:shortestPath

bash 复制代码
MATCH path = shortestPath((n:AGENCY) -[*..10]->(m:AGENCY))
WHERE n.name = "北京市昌平区定泗路" AND m.name = "上海市浦东新区南汇"
RETURN path

查询两个网点之间所有的路线中成本最低的路线

这里指定最大深度为10(如果成本相同,转运节点最少)

bash 复制代码
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()等;
  • relationships()函数,获得属性的详细信息;

查询结果如下,与上面的查询结果类似;

5.3.4 分页查询

当数据量特别大的时候,采用分页查询就是不错的选择了,比如,使用上面的数,下面的两个场景的查询

bash 复制代码
#分页查询网点,按照bid正序排序,每页查询2条数据,第一页
MATCH (n:AGENCY) 
RETURN n ORDER BY n.bid ASC SKIP 0 LIMIT 3

#第二页
MATCH (n:AGENCY) 
RETURN n ORDER BY n.bid ASC SKIP 3 LIMIT 3

5.3.5 更新数据

更新数据是使用SET语句进行标签、属性的更新。SET操作是幂等性的。

更新/设置新的属性

bash 复制代码
MATCH (n:AGENCY {name:"北京市昌平区新龙城"})
SET n.address = "龙跃苑四区3号楼底商101号"
RETURN n

通过remove移除属性

bash 复制代码
MATCH (n:AGENCY {name:"北京市昌平区新龙城"}) REMOVE n.address RETURN n

增加一个address属性

bash 复制代码
MATCH (n:AGENCY) WHERE n.address IS NULL SET n.address = "暂无地址" RETURN n

5.3.6 删除数据

删除数据通过DELETE、DETACH DELETE完成。其中DELETE不能删除有关系的节点,删除关系就需要DETACH DELETE了。

bash 复制代码
#删除节点
MATCH (n:AGENCY {name:"航头营业部"}) DELETE n

#有关系的节点是不能直接删除的
MATCH (n:AGENCY {name:"北京市昌平区新龙城"}) DELETE n

#删除节点和关系
MATCH (n:AGENCY {name:"北京市昌平区新龙城"}) DETACH DELETE n

#删除所有节点和关系,慎用!
MATCH (n) DETACH DELETE n

有关系的节点是不能直接删除的,如下,当删除 "北京市昌平区新龙城"这个节点时抛错

5.4 索引操作

在很多数据存储引擎中都有索引的存在,合理使用索引可以提升数据检索效率,在Neo4j中同样也支持索引,对字段做索引可以提升查询速度。

5.4.1 创建索引

语法如下,其中:OPTIONS子句指定索引提供程序和配置。

bash 复制代码
CREATE [TEXT] INDEX [index_name] [IF NOT EXISTS]
FOR (n:LabelName)
ON (n.propertyName)
[OPTIONS "{" option: value[, ...] "}"]

如下,给AGENCY创建索引;

bash 复制代码
CREATE TEXT INDEX agency_index_bid IF NOT EXISTS FOR (n:AGENCY) ON (n.bid)

5.4.2 删除索引

语法

DROP INDEX index_name

比如删除上面创建的索引

六、写在最后

本文通过大量的篇幅,全方位介绍了Neo4j这款优秀的图数据库的使用,希望对看到的同学有用,为你今后技术选型提供一个参考依据,感谢观看。

相关推荐
Gabriel_liao27 分钟前
Docker安装Neo4j
docker·容器·neo4j
misakivv33 分钟前
Neo4j Desktop 无法打开
neo4j
Moshow郑锴3 天前
Neo4j Graph Data Science Certification exam! 题库1
neo4j·knowledge graph·考试认证·data science
新手小袁_J3 天前
实现Python将csv数据导入到Neo4j
数据库·python·neo4j·《我是刑警》·python连接neo4j·python导入csv·csv数据集导入neo4j
ZHOUPUYU3 天前
最新 neo4j 5.26版本下载安装配置步骤【附安装包】
java·后端·jdk·nosql·数据库开发·neo4j·图形数据库
シ風箏3 天前
Neo4j【环境部署 02】图形数据库Neo4j在Linux系统ARM架构下的安装使用
linux·数据库·arm·neo4j
清风ꦿ3 天前
neo4j 图表数据导入到 TuGraph
python·neo4j·knowledge graph
Nice night4 天前
Neo4j插入数据逐级提升速度4倍又4倍
neo4j
abments9 天前
neo4j删除所有数据
数据库·neo4j
入戏三分_s9 天前
Neo4j常用命令
java·前端·neo4j