Neo4j基本使用与Cypher语言基础

图数据库简介

什么是图?

图是由实体以及实体间的关系组成的结构,这种结构可以抽象表示现实世界中的事物及事物间的关系。我们可以用节点/Node/Vertex表示实体、用节点间的连边/Ralationship/Edge/表示节点间的关系。

举例来说,我们的朋友圈可以通过图结构进行抽象,每个人作为一个节点,若两个人之间存在关系则认为两个节点具有连边,由此构造出社交网络。

更多关于图的介绍或相关研究可以查阅图论、复杂网络科学,前者为侧重抽象数学层面的领域,后者更侧重对使用图结构对复杂系统的性质进行建模分析。

为什么需要图数据库?

众所周知,关系型数据库也可以存储“图‘结构的数据,我们可以通过设计一张MySQL表存储某一个实体(节点)的信息,每个实体所具有的属性对应着MySQL表的字段(列)。通过关联表或者外键关联关系等方式存储节点间的关系,这样的设计可以支持对图数据的存储和检索。那么,为什么需要在一般的关系型数据库之外,专门设计一种叫“图数据库”的东西呢?

这里提一句奥卡姆剃刀原则:“如无必要,勿增实体。“

那么,图数据库的必要性是?

主流关系型数据库的缺陷

所谓缺陷,其实不是绝对的缺陷,而是特定需求、场景下的缺陷。假设我们要对复杂网络相关的数据进行分析,其中可能会经常需要对节点的特征进行深度优先的搜索。在一般关系型数据库中,我们查询具有一阶关联关系的节点对信息需要使用JOIN关联两个表(一个节点吧,一个节点关系表)进行查询,如果涉及到多阶关系的查询(如查询节点的多阶邻居,甚至更复杂的多种关系),那么关系型数据库就需要同时JOIN多个表乃至使用子查询,而针对我们的关系查询需求而言,关系数据库的查询会变得非常复杂且效率不高。

假设你已经认同了关系数据库在涉及高阶关系查询上的困境,再进一步考虑一个场景:我们可能会需要经常对关系数据(包括关系的属性)进行更新!比如金融、商业领域的数据变化频率很高,关系型数据库既然在处理高阶关系查询时效率就低,那数据更新就更加不用期待了。

因此,我们需要一种专用的数据库,用于存储和处理图数据并能够在处理复杂关系查询/更新时有较高的效率,这就是图数据库,其中最具有代表性的一种实现就是Neo4j。

权衡(Trade Off)

当然,使用图数据库能够进行高效率复杂关系查询,但是在存储空间和内存需求上要求更高了。所以,如果你对数据库的需求不在于显式存储数据关系,那可以使用关系型数据库节省内存空间。

Neo4J生态工具

Neo4J Desktop: Neo4j的桌面端管理软件。

Neo4J Browser:Neo4J的在线浏览器接口,可以查询管理数据库中的数据,提供使用Cypher语言对图数据进行基本可视化的功能。也提供了很多快捷命令(如用户添加、角色添加等)

Cypher语言

基本介绍

类似SQL在MySQL、PostgreSQL等数据库中的作用,Cypher就是图数据库的一种查询语言。但Cypher的使用与SQL却有很多不同。总结起来,Cypher查询语句的特征可以总结为“模式”查询,即通过描述实体-关系的“模式”,并为模式各组成部分进行变量命名,将需要的变量返回即可得到查询结果,或者修改、删除对应变量即可完成对指定条件的数据进行变更。

Cypher CheetSheet:Cypher Cheat Sheet - Neo4j Documentation Cheat Sheet

Cypher文档:Introduction - Cypher Manual

一些工具:cypher-shell、neo4j-admin

关于Cypher的系统性学习可以注册Neo4j官网中的课程,完成后可以获得证书:

下面仅为个人笔记,便于查阅:

基本关键字

Cypher是对节点、节点间的关系及属性进行增删改查的类SQL语言。主要有如下关键字:

  • MATCH

  • MERGE

  • CREATE

  • SET

  • DELETE

  • DETACH DELETE

  • RETURN

查询节点

查询某种关系类型的根节点
MATCH (n:NodeType)
WHERE NOT EXISTS(()<-[:RelationType]-(n:NodeType))
RETURN n

查询关系

聚合查询

Cypher语言中的聚合函数与SQL中的命名类似,计算总数的函数为COUNT,计算总和的函数为SUM。

聚合函数及使用示例

  • COUNT

  • SUM

查询数据库中存在的节点和关系总数
MATCH ()-[r]->() RETURN count(r)
MATCH (n) RETURN count(n)

查询各类节点的数量
MATCH (n) RETURN labels(n), count(*)
查看各类关系的数量
MATCH ()-[r]->()
RETURN type(r), count(*)

模糊查询

模糊查询并非使用LIKE关键字,而是使用CONTAINS,如:

MATCH p=(n:NodeType)-->() WHERE n.name CONTAINS '需要模糊查询的关键字' RETURN p

批量变更关系类型

MATCH (a)-[r:OLD_RELATION]->(b)
CREATE (a)-[rNew:NEW_RELATION]->(b)
SET rNew = r
WITH r
DELETE r

删除数据

删除关系

MATCH (n)-[r:TEST_TYPE]->()
DELETE r, n

删除孤立节点

MATCH (n:NodeType) WHERE NOT (n)--() DELETE n

多跳查询

二跳查询

MATCH p=(n:NodeType{name:'NodeName'})-[r:Rel1]->()-[:Rel2]->(re)  RETURN re.name,re.id

递归多跳查询

在关系类型后加*符号即可实现递归查询

MATCH p=(n:NodeType{name:'NodeName'})-[r:Rel1*]->(re)  RETURN re.name,re.id

Neo4j查询结果集导出csv/json

通过Cypher命令查出的表格数据可以使用Neo4j Browser的Export CSV/Export JSON功能导出。

图数据库示例数据集

图数据库图算法支持

Python操作Neo4j数据库

  • py2neo github 1.2 star

  • neo4j github 800+ star

Nginx代理转发Neo4j服务

有时候可能希望将neo4j默认服务(neo4j browser等)开放给互联网上的用户使用,并且希望希望通过nginx进行反向代理,简单的做法可以参考如下流程:

  1. 配置nginx.conf文件,新建stream代理规则,用于支持neo4j采用websocket协议通信的服务.

stream {
        upstream neo4j {
                server 127.0.0.1:7687;
        }

        server {
                 listen       YOUR_PORT;
                 proxy_pass  neo4j;

        }
}
  1. 配置xxx.conf文件,新建http server代理规则,用于支持neo4j browser(http服务).
server {
   listen      YOUR_PORT;
   server_name  YOUR_HOSTNAME_OR_IP;
   location /graph/ {
           proxy_hide_header Content-Security-Policy;
           proxy_hide_header X-Frame-Options;
           proxy_pass http://127.0.0.1:7474/;

   }
}

http://127.0.0.1:7474/是neo4j Browser的默认服务地址,当然也可以在配置文件修改默认端口。

这两条配置是为了让neo4j browser可以通过iframe嵌入到另一个站点,否则进行iframe嵌入会受到限制。

           proxy_hide_header Content-Security-Policy;
           proxy_hide_header X-Frame-Options;
CoolCats
CoolCats
理学学士

我的研究兴趣是时空数据分析、知识图谱、自然语言处理与服务端开发