(说明:下文指的Neo4j全部指代的是3.x版本。)
一、摘要
本文主要记录Neo4j的相关基本知识,包括:
1、Neo4j的基本数据模型;
2、图数据库的使用场景;
3、Cypher的基本语法和部分函数;
4、Neo4j的扩展包APOC和Cypher扩展;
5、查询性能优化基本介绍;
6、Neo4j结合实例分析;
通过以上几点可以得出本文主要是记录neo4j的一些功能,方便后面进行查询。对于环境搭建以及数据导入等不做描述。
二、Neo4j的基本数据模型
2.1、基本数据结构
我们先介绍下Neo4j中的数据模型。主要包括四种数据结构:
1、节点:通常用于存储实体信息。比如一个人可以作为一个节点,一辆车作为一个节点;
2、关系:用来连接节点的实体。比如一个人A和另一个人B是夫妻关系、朋友关系等。每个关系实体必须有起始节点和结束节点,所以关系是有指向的。还需要强调一点,关系只能是一个类型,比如A和B之间的不同关系要用两种关系描述;
3、属性:节点和关系都是属性的容器,属性由键值对组成,类似于java对象中的成员属性;
4、标签:对一类节点的统称,更加方便查询和neo4j本身的维护,同一标签的节点属性尽量一致(neo4j未做硬性限制)。
属性支持的数据类型包括(懒得打了,官网复制的https://neo4j.com/docs/cypher-manual/current/syntax/values/):
- Number, an abstract type, which has the subtypes Integer and Float
- String
- Boolean
- The spatial type Point (空间)
- Temporal types: Date, Time, LocalTime, DateTime, LocalDateTime and Duration (时间)
2.2、图建模
2.2.1图建模的Try
1、查询性能设计:查询驱动模型,一定要根据用户的需求来设计模型,从用户需求中脱离出节点和关系;
2、用例关系匹配:在neo4j中,新增节点之间的不同类型关系,代价是很低的。有时关系的划分有时候可以尽量细,但是要注意命名,尽量不要使用通用命名,例:HAS_A,而要使用能具体描述这个关系的名字;
3、查找n元关系:例如一首歌《梯田》,它的词曲是由歌曲作者创作,它的出版是由一个公司执行的,它的MV是由一个艺术家表演,那么就可以组成下面的关系:
4、节点粒度:在图数据库建模时,倾向于使用比我们习惯的关系模型具有更高粒度、更精细的数据模型。当你在考虑一个属性是否成为一个节点的时候(比如用这个属性进行某种筛选),以实际查询速度为准;
5、适当使用图内索引:使用索引可以很方便的进行范围查询、时间序列、邻近搜索,但是不能 ALL IN INDEX,类似于MySQL创建索引的考虑点;
2.2.2图建模的Avoid
1、使用丰富的属性:粒化模式的反模式;
2、多概念节点:一个节点有多重身份,考虑是否将部分属性移除当成另外的label;
3、未连接的图:既没有关系的节点;
4、密集的节点模式:尽量避免超级节点的产生,即一个节点有很多关系,比如周杰伦的粉丝;
二、图数据库的使用场景
上面介绍了图数据的基本数据模型,本章主要介绍图数据库的特点和使用场景。
图数据库提供了一种全新的解决问题的模型:图,注意不是照片对应的图片。在关系型数据库中关系查询是一个很耗性能的操作,相当于笛卡尔积查询。但是在图数据库,关系是被显示存储,这样只需要直接遍历即可。在上面也介绍到,关系上面是可以有属性的,这一点相对于RDBMS是完全不同的。
适合图数据库的使用场景:
1、复杂查询:本质上包含大量的复杂连接操作。在图数据库中,连接操作将不复存在,而只是需要从一个节点开始指定一级或者多级关系,然后再指定到另一个节点;
2、实时数据的点击流查询:图数据库能快速处理更多种类的复杂查询,数据可以是重复的或近实时的更新;
3、路径查询:类似于第一条,优化了关联查询;
不建议使用图数据库的场景:
1、大集合查询:面向集合的数据库,关系数据库的性能更高;
2、图的全局操作:查找节点集群、发现节点间位置的关系模式、确定特定图的中心等问题都是从全局上研究图,这类操作需要另外一套更专业,性能更高的IT架构去完成,并且时间往往是需要几个小时,甚至于几周;
3、简单聚合查询:简单查询中,读写聚合数据使用图处理非常低效,更适合采用面向聚合操作的键值存储或文档存储。如果复杂性较低,使用图数据库的又是也会较低。
三、Cypher的基本语法和部分函数
3.1、基本查询关键词和基本查询语法
本节会先列出一个查询语句,然后对其进行拆分,介绍相关的关键词和基本语法。(对于增删改、以及CSV导入未涉及)
语句:MATCH(u:User)-[r1:FRIEND]->(someone:User)<-[r2:FRIEND]-(u1:User) WHERE u.userId = "..." and u1.userId = "..." RETURN someone ORDER BY someone.userId DESC(User是一个标签,FRIEND是一个关系,userId是User标签节点的一个属性)
上面语句是对于指定的两个用户,查询他们共同的朋友的所有信息。
MATCH:用于描述数据库应该匹配的模式。总是作为结构化查询组件的开头,类似于 SELECT ... FROM ...;
WHERE:对于MATCH的结果集进行筛选,对于节点、关系相关信息都可以进行判断;
RETURN:返回结果集,可以是节点、节点属性、关系、关系属性以及各种聚合结果或者汇总结果以及三角函数等数学计算;
基本语法:MATCH(n1:Node1)-[r:RELATIONSHIP]->(n2:Node2) WHERE condition RETURN result;
结合上面的例子,总结下Cypher 的关键特性:
- 声明式的(Declarative):类似于Mysql,告诉数据库我们要什么,而不是告诉数据库怎么去取数据;
- 具有表现力的(Expressive):使用了圆括号、方括号以及连接各个部分的箭头的这种风格,很容易让人理解查询语句想要干嘛;
- 模式匹配的;
- 幂等的。
3.2、扩充点
分页查询:SKIP startIndex LIMIT pageSize;
串联查询:MATCH Cypher1 WITH result1 OPTIONAL MATCH Cypher2 RETURN result2;
WITH:获取上个查询语句中的结果,但是不返回,而是传递给下一个查询;
OPTIONAL MATCH:相当于MATCH,但是是对于缺失的部分会返回null,类似于Mysql 的 outer join;
RETURN:串联查询中也只能出现一个;
索引:创建索引-CREATE INDEX ON :LabelName(propertyName),查看索引和约束-:schema或者单独查看索引CALL db.indexes;
约束:CREATE CONSTRAINT ON (nodeName:LabelName) ASSERT nodeName.propertyName IS UNIQUUE,创建约束同时会为这个属性创建索引;
查询多级关系:-[:TYPEminHops..maxHops]->,TYPE是指的关系类型,也可以不指定,只需要添加即可,例如 -[*1..3]->,查了三级关系;
3.3、语法约定
- 节点别名用小写驼峰(以小写字母开头)。
- 标签用大写驼峰(以大写字母开头)。
- 关系用蛇形大写(类似IS_A)。
- 属性名用小写驼峰。
- 关键词全部用大写。
四、Neo4j的扩展包APOC和Cypher扩展
4.1、APOC介绍(安装注意版本一致)
从2009年开始,APOC作为一个函数和过程的集合,可以在Cypher中使用。它包括以下类别:
- 集合操作(排序、最小值、最大值等)。
- 图操作(索引和重构)。
- 文本搜索。
- 转换。
- 排序。
- 地理空间操作。
- 数据集成。
- 报表。
- 获取表示图的元图。
4.2、函数和过程
从复杂性对于两者进行区分:
函数:相对简单。其设计的目的是通过读取数据库数据并计算返回一个结果,可以直接在Cypher语句中使用;
过程:可以对数据进行修改并返回多个结果,调用必须使用关键词 CALL。
4.3、常用用法
1、通过关键词搜索函数和过程:CALL apoc.help('meta')
2、图概述:CALL apoc.meta.graph (V3.1及以下)或 CALL db.schema() (V3.2及以上)
3、Cypher 语句限时执行:CALL spoc.cypher.runTimeboxed(CypherStatement, params, timeoutInMs)
例:CALL spoc.cypher.runTimeboxed('MATCH(n) return n limit 10',NULL,2)。
有需求推荐直接阅读官网:https://neo4j.com/docs/labs/apoc/3.5/
4.4、Cypher扩展
这一部分只进行了功能记录。
1、构建扩展工程:包括创建函数和创建过程,主要是使用的注解会不同。
2、定制聚合器。
3、非托管扩展:HTTP 和 JAX-RS refreshers、JSON响应流式化。
五、查询性能优化基本介绍
本章主要介绍性能关键词、常用优化手段以及相关注意事项。
5.1、Explain 和 Profile 关键词
这两个关键的主要作用都是用来查看执行计划。两者区别在于,Explain 不会将结果查询出来,这样每个执行计划关联的 Rows 不准确;Profile 会将结果查询出来的执行计划展示出来。下面在解释下两个概念:
- 查询计划:从上往下看。
- 运算符:上面截图中的每个方框相当于一个运算符。
5.2、常用优化手段
主要有两条:查询命中索引和强制使用标签。对于强制使用标签,在对于一个节点有多个标签的时候,特别有用。
强制使用标签举例:MATCH(u:User:Teacher) USING SCAN u:Teacher WHERE u.subject = 'Math' RETURN u (USING SCAN nodeName:labelName )
5.3、注意事项
1、Explain所有查询:注意在合适的数据集上进行测试,确定好性能瓶颈,一般就是看数据库hits 最多的运算符。
2、行:在我们的查询计划中,如果行数不是从上向下快速递减的话,需要考虑是否使用了足够的标签、创建了足够多的索引以及是否在使用的属性上创建了索引。
3、不要过度消耗资源:只返回需要的数据。
4、返回笛卡尔积级别的数据:这个是很明显的,例如
MATCH (n),(m) RETURN n,m
5、简单:使用WITH 关键词将查询切成几块,方便阅读。
六、Neo4j结合实例分析
还没有开发Demo,后续补充。