精通Neo4j-学习笔记

一、Neo4j图数据库基础

1、数据库实现高效遍历的关键
免索引邻接:数据库中的每个节点都会维护与它相邻节点的引用,因此相当于每个节点都具有与它相邻节点的微索引。
2、底层存储结构
从宏观角度来说,Neo4j中仅仅只有两种数据类型:
	1、节点(Node):
		节点类似于E-R图中的实体(Entity)。每一个实体可以有零个或多个属性(Property),这些属性以键值对的形式存在。属性没有特殊的类别要求,同时每个节点还具有相应的标签(Label),用来区分不同类型的节点。
		节点存储文件用来存储节点的记录,文件名为neostore.nodestore.db。节点记录的长度为固定大小,每个节点记录的长度为9字节。格式为Node:inUse+nextRelId+ nextPropId。
		● inUse:1表示该节点被正常使用,0表示该节点被删除。
		● nextRelId:该节点的下一个关系ID。
		● nextPropId:该节点的下一个属性ID。
	2、关系(Relationship):
		关系也类似于E-R图中的关系(Relationship)。一个关系有起始节点和终止节点。另外,与节点一样,关系也能够有自己的属性和标签。
		关系存储文件用来存储关系的记录,文件名为neostore.relationshipstore.db。关系存储区的记录大小也是固定的,每个节点记录的长度为33字节。格式为:Relationship:inUse+firstNode+secondNode+relType+firstPrevRelId+firstNextRelId+secondPrevRelId+secondNextRelId+nextPropId。
		● inUse,nextPropId:作用同上。
		● firstNode:当前关系的起始节点。
		● secondNode:当前关系的终止节点。
		● relType:关系的类型。
		● firstPrevRelId & firstNextRelId:起始节点的前一个和后一个关系的ID。
		● secondPrevRelId & secondNextRelId:终止节点的前一个和后一个关系ID。
	属性记录的物理存储放置在neostore.propertystore.db文件中。属性的存储记录也是固定长度(33字节)。每个属性记录包含4个属性块和属性链中下一个属性的ID。属性链是单向链表,而关系链是双向链表。一个属性记录中可以包含任何Java虚拟机(JVM)支持的基本数据类型、字符串、基于基本类型的数组以及属性索引文件(neostore.propertystore.db.index)。属性索引文件主要用于存储属性的名称,属性索引的值部分存储的是指向动态内存的记录或者内联值,短字符串和短数组会直接内联在属性存储记录中。当长度超过属性记录中的propBlock长度限制之后,会单独存储在其他的动态存储文件中。
Neo4j中有两种动态存储:
	1、动态字符串存储(neostore.propertystore.db.strings)
	2、动态数组存储(neostore.propertystore.db.arrays)。
	动态存储记录是可以扩展的,如果一个属性长到一条动态存储记录仍然无法完全容纳时,可以申请多个动态存储记录以便在逻辑上进行连接。
3、遍历方式
Neo4j每个节点记录都包含一个指向该节点的第一个属性的指针和联系链中第一个联系的指针。要读取一个节点的属性,从指向第一个属性的指针开始,遍历整个单向链表结构。要找到一个节点的关系,从指向的第一个关系开始,遍历整个双向链表,直到找到了感兴趣的关系。一旦找到了感兴趣关系的记录,我们就可以与使用和查找节点属性一样的方法查找关系的属性(如果该关系存在属性)。

二、Neo4j基础入门

1、Neo4j命令
● neo4j console:打开Neo4j的控制台。
● neo4j start:启动Neo4j。
● neo4j stop:关闭Neo4j。
● neo4j restart:重启Neo4j。
● neo4j status:查看Neo4j运行状态。
● neo4j install-service:安装Neo4j在Windows系统上的服务。
● neo4j uninstall-service:卸载Neo4j在Windows系统上的服务。
2、基本元素与概念
1、节点(Node):用以表示一个实体记录,节点可以包含多个属性(Property)和多个标签(Label)。
2、关系(Relationship):节点需要连接起来才能构成图。关系就是用来连接两个节点的,关系又称为图论的边(Edge),其始端和末端都必须是节点,关系不能指向空也不能从空发起。关系和节点一样可以包含多个属性,但关系只能有一个类型(Type)。由于关系可以是有方向的,所以可在由节点、关系组成的图中进行遍历操作。在图的遍历操作中,我们可以指定关系遍历的方向或者指定为无方向,因此在创建关系时不必为两个节点创建相互指向的关系,而是在遍历时不指定遍历方向即可。
3、属性:节点和关系都可以有多个属性。属性是由键值对组成的,属性值可以是基本的数据类型,或者由基本数据类型组成的数组。Neo4j属性值的基本类型:boolean、byte、short、int、long、float、double、char、string。
4、路径:当使用节点和关系创建了一个图后,在此图中任意两个节点间都是可能存在路径(Path)的。图中任意两节点都存在由节点和关系组成的路径,路径也有长度的概念,也就是路径中关系的条数。
5、遍历:遍历(Traversal)一张图就是按照一定的规则,根据它们之间的关系,依次访问所有相关联的节点的操作。遍历规则可以是广度优先,也可以是深度优先。

三、Neo4j之Cypher

1、Cypher命令
CREATE:创建节点和关系
DELETE:删除节点和关系
SET:添加或更新标签和属性
REMOVE:删除节点和关系的标签和属性
MATCH:检索有关节点,关系和属性
WHERE:提供条件过滤检索数据
RETURN:返回查询结果
SKIP:跳过指定数量数据
LIMIT:读取指定数量数据
ORDER BY:排序检索数据
MERGE:匹配已经存在的或者创建新节点和模式,对有唯一性约束的情况非常有用
2、Cypher语法
1、节点语法:用一对圆括号来表示节点。
	(matrix:Movie {title: "The Matrix"})
		matrix为节点变量,此变量的可见范围局限于单个语句。
		Movie标签声明了节点的类型。
		Neo4j节点索引也会使用到标签,每个索引都是建立在一个标签和属性的组合上。节点的属性以key/value列表的形式存在,并外加一对大括号。属性可以存储信息和(或)限制模式。
2、关系语法:使用一对短横线(即--)表示一个无方向关系。有方向的关系在其中一段加上一个箭头(即<--或-->)。方括号表达式[…]可用于添加详情。里面可以包含变量、属性和(或者)类型信息。
	-[ role: ACTED_IN { roles: ["nes"] } ]->
3、模式语法:将节点和关系的语法组合在一起可以表达模式。
	(keanu:Person:Actor {name: "Keanu Reeves"))-[role:ACTED IN {roles: ["Neo"]}]->(matrix:Movie (title: "The Matrix" })
	为了增强模块性和减少重复,Cypher允许将模式赋给一个变量。这使得匹配到的路径可以用于其他表达式。如:acted_in=(:Person)-[:ACTED IN]->(:Movie)
3、查询和更新图
Cypher语句既可用于查询,又可用于更新图数据。但一个Cypher查询部分不能同时匹配和更新图数据。每个部分要么读取和匹配图,要么更新。
如果需要从图中读取,然后更新图,那么该查询隐含地包含两个部分——第一部分是读取,第二部分是写入。如果查询只是读取,Cypher将采用惰性加载(Lazy Load),事实上并没匹配模式,直到需要返回结果时才去实际匹配。在更新查询语句中,所有读取操作必须在任何写操作发生之前完成。
当希望使用聚合数据进行过滤时,必须使用WITH将两个读语句部分连接在一起。第一部分做聚合,第二部分过滤来自第一部分的结果。如下所示:
	MATCH(n {name:"John'})-[:FRIEND]-(friend) WITH n,count(friend) As friendsCount WHERE friendsCount>3 RETURN n,friendsCount
任何查询都可以返回数据。RETURN语句有三个子语句,分别为SKIP、LIMIT和ORDER BY。如果返回的图元素是刚刚删除的数据,需要注意的是这时数据的指针将不再有效,针对它们的任何操作都无法正确运行。
4、事务
任何更新图的查询都运行在一个事务中。因此一个更新查询要么全部成功,要么全部失败。Cypher或者创建一个新的事务,或者运行在一个已有的事务中
	● 如果运行上下文中没有事务,Cypher将创建一个,一旦查询完成就提交该事务。
	● 如果运行上下文中已有事务,查询就会运行在该事务中。直到该事务成功地提交之后,数据才会持久化到磁盘中去。
5、唯一性
当进行模式匹配时,Neo4j将确保单个模式中不会包含匹配到多次的同一个图关系。例如:查找一个用户的朋友的朋友不应该返回该用户。
6、类型
Cypher支持的数据类型有:数值型、字符串、布尔型、节点、关系、路径、映射(Map)和列表(List)。
7、表达式
case表达式
	1、简单case表达式:计算表达式的值,然后依次与WHEN语句中的表达式进行比较,直到匹配上为止。如果未匹配上,则ELSE中的表达式将作为结果。如果ELSE语句不存在,那么将返回null。
		语法:
			CASE test
			WHEN value THEN result
			[WHEN ...]
			[ELSE default]
			END
		参数:
			● test:一个有效的表达式。
			● value:一个表达式,它的结果将与test表达式的结果进行比较。
			● result:如果value表达式能够与test表达式匹配,则它将作为结果表达式。
			● default:没有匹配的情况下的默认返回表达式。
	2、一般的Case表达式:计算表达式的值,然后依次与WHEN语句中的表达式进行比较,直到匹配上为止。如果未匹配上,则ELSE中的表达式将作为结果。如果ELSE语句不存在,那么将返回null。
		语法:
			CASE 
			WHEN predicate THEN result
			[WHEN ...]
			[ELSE default]
			END
		参数:
			● predicate:判断的断言,以找到一个有效的可选项。
			● result:如果predicate匹配到,result就作为结果表达式。
			● default:没有匹配到情况下,默认返回表达式。
8、变量
变量名是区分大小写的。它可以包含下划线、字母(a~z、A~Z)和数字(0~9),但必须以字母开头。如果变量名需要用到其他字符,则可以用反向单引号(`)将变量名括起来。比如,如果变量名中包含特殊字符μ,则可以按如下方式使用:match(`μg`:food) return `μg`
变量仅在同一个查询内可见。它不能被用于后续的查询。如果有WITH连接起来的多个查询部分,变量必须列在WITH语句中才能应用到后续部分。
9、参数
参数能够用于WHERE语句中的字面值和表达式,START语句中的索引值、索引查询以及节点和关系的id。参数不能用于属性名、关系类型和标签,因为这些模式将作为查询结构的一部分被编译进查询计划。
合法的参数名是字母、数字以及两者的组合。
例子:
	参数:{ "name": "Johan" }
	查询方式1: match (n)  where n.name = $name return n
	查询方式2: match (n { name:$name } )  return n
10、运算符
数学运算符:+、-、*、/、%、^
比较运算符:=、<>、<、>、<=、>=、IS NULL、IS NOT NULL。
布尔运算符:AND、OR、XOR、NOT。
连接字符串的运算符为+,正则表达式的匹配运算符为=~
列表的连接可以通过+运算符,可以用IN来检查列表中是否存在某个元素。
链式比较运算:x < y <= z等价于x < y AND y <= z
11、注释
Cypher语言用双斜线//来注释行
12、模式
12.1、节点模式:
	节点使用一对圆括号表示,然后中间含一个名字。例如:(a)
12.2、关联节点模式:
	Cypher使用箭头来表达两个节点之间的关系,两个节点和从其中一个节点到另外一个节点的关系。两个节点分别命名为a和b,关系是有方向的,从a指向b。例如:(a)-->(b)
	这种描述节点和关系的方式可以扩展到任意数量的节点和它们之间的关系。
12.3、标签:
	模式除了可以描述节点之外,还可以用来描述标签。比如:(a:User)-->(b)
	也可以描述一个节点的多个标签,如:(a:User:Admin)-->(b)
12.4、指定属性:
	属性在模式中使用键值对的Map结构来表示,然后用大括号包起来。例如,一个有两个属性的节点如下所示:(a { name: "Andres", sport: "Brazilian Ju-Jitsu" })
12.5、描述关系:
	关系可以赋予变量名,同时关系可以有类型,但只能有一个类型,如:(a)-[r:REL_TYPE]->(b)
	如果所描述的关系可以是一个类型集中的任意一种类型,可以将这些类型都列入模式中,它们之间以竖线“|”分隔,例如:(a)-[r:TYPE1 | TYPE2]->(b)
	***注意:上述模式仅适用于描述已经存在的数据(如在MATCH语句中),而在CREATE或者MERGE语句中是不允许的,因为一个关系不能创建多个类型。
	很多关系(以及中间的节点)可以采用指定关系的长度的模式来描述,例如:(a)-[*2]->(b)
	关系的长度也可以指定一个范围,这被称为可变长度的关系,例如:(a)-[*3..5]->(b)
	长度的边界也是可以省略的,如描述一个路径长度大于等于3的路径:(a)-[*3..]->(b)
	两个边界都可以省略,这允许任意长度的路径,例如::(a)-[*]->(b)
	***注意:可变长度的关系不能用于CREATE和MERGE语句。
12.6、路径变量:
	连接在一起的一系列节点和关系称为路径。Cypher允许使用标识符给路径命名,例如:p= (a)-[*3..5]->(b)
	***注意:在MATCH、CREAT和MERGE语句中可以这样做,但当模式作为表达式的时候不能这样做。
13、列表
13.1、概述:
	可以使用方括号和一组以逗号分隔的元素来创建一个列表。例如:return [1,2,3,4,5] as list
	可以使用方括号[]访问列表中的元素。例如:return range(0,10)[3]
	索引也可以为负数,这时将以列表的末尾作为开始点访问。例如:return range(0,10)[-3]
	可以在[]中指定列表返回指定范围的元素。它将提取开始索引到结束索引的值,但不包含结束索引所对应的值。例如:return range(0,10)[0..3]
	如果是一个range的索引值越界了,那么直接从越界的地方进行截断以返回结果。如果是单个元素的索引值越界了,则返回null。
	可以用size函数获取列表的长度,例如:return size(range(0,10)[0..3])
13.2、列表推导式:
	return [ x in range(0,10) where x%2 =0 | x^3] as result   (先过滤再映射)
13.3、模式推导式:
	match (a:Persn { name: 'Charlie Sheen' })
	return [ (a)-->(b) where b:Movie | b.year ] as years
13.4、map投射:
	Map投射以指向图实体且用逗号分隔的变量簇开头,并包含以{}包括起来的映射元素。其语法:map_variable {map_element, [, ...n] }
	一个map元素投射一个或多个键值对到map投射。这里有4种类型的map投射元素:
		● 属性选择器:以投射属性名作为键,map_variable中对应键的值作为键值。
		● 字面值项:来自任意表达式的键值对,如key: <expression>。
		● 变量选择器:投射一个变量,变量名作为键,变量的值作为投射的值。它的语法只有变量。
		● 全属性选择器:射来自map_variable中的所有键值对。
		提示:如果map_variable的值指向一个null,那么整个map投射将返回null。
	使用样例:
		match (actor:Person {name: "Charlie Sheen"}) -[:ACTED_IN]->(movie:Movie)
		return actor { .name, .realName, movies: collect( movie { .title, .year} ) }
13.5、字面值映射:

字面值映射

14、空值
空值null在Cypher中表示未找到或者未定义。
null不等于null,两个未知的值并不意味着它们是同一个值。因此,null = null返回null,而不是true。
14.1、空值的逻辑运算:
	逻辑运算符包括AND、OR、XOR、IN、NOT,把null当作未知的三值逻辑值。
14.2、空值与IN:
	如果列表中存在某个值,则结果返回true;如果列表中包含null值并且没有匹配到值,则结果返回null;否则结果为false。
14.3、返回空值的表达式:
	● 从列表中获取不存在的元素:[][0]、head([])。
	● 试图访问节点或者关系的不存在的属性:n.missingProperty。
	● 与null做比较:1 < null。
	● 包含null的算术运算:1 + null。
	● 包含任何null参数的函数调用:sin(null)。
15、语句
语句可分为三类,包括读语句、写语句和通用语句。
	● 读语句:包括MATCH、OPTIONAL MATCH、WHERE、START和Aggregation。
	● 写语句:包括LOAD CSV、CREATE、MERGE、SET、DELETE、REMOVE、FOREACH和CREATE UNIQUE。
	● 通用语句:包括RETURN、ORDER BY、LIMIT、SKIP、WITH、UNWIND、UNION和CALL。
15.1、match语句
用于指定的模式检索数据库。
15.1.1、查找节点
		1、查询所有节点:match (n) return n
		2、查询带有某个标签的所有节点:match (movie:Movie) return movie.title
		3、查询关联节点:match (director) --(movie) return movie.title
		4、匹配标签:match (director {name: "Oliver Stone"}) --(movie) return movie.title
15.1.2、查找关系
	1、外向关系:match (:Person {name: "Oliver Stone"}) -->(movie) return movie.title
	2、有向关系和变量:match (:Person {name: "Oliver Stone"}) -[r]->(movie) return type(r)
	3、匹配关系类型:match (:Movie {title: "Wall Street"}) <-[:ACTED_IN]-(actor) return actor.name
	4、匹配多种关系类型:match (:Movie {title: "Wall Street"}) <-[:ACTED_IN | DIRECTED]-(actor) return actor.name
	5、匹配关系类型和使用关系变量:match (wallstreet {title: "Wall Street"}) <-[r:ACTED_IN]-(actor) return r.role
15.1.3、关系的深度
	1、带有特殊字符的关系类型:某些时候数据库中可能会有非字母字符的类型,或者中间含有空格。可以使用反引号“`”将它们括起来。例如:match (n {name: `Rob Reiner`}) -[r]->() return type(r)	。
	2、多个关系:关系可以多语句以()--()的形式来表达,或者它们相互连接在一起。例如:match (n {name: `Rob Reiner`}) -[:ACTED_IN]->(movie)<-[:DIRECTED]-(director) return movie.title, director.name。
	3、可变长度关系:-[:TYPE*minHops..maxHops]->  
		minHops和maxHops都是可选的,默认值分别为1和无穷大。当没有边界值的时候,点也是可以省略的。当只设置了一个边界的时候,如果省略了点,则意味着这是一个固定长度的模式。
		示例:match (:Person {name: "Oliver Stone"}) -[:ACTED_IN*1..3]->(movie:Movie) return movie.title
	4、具有多种关系类型的可变长度关系:match (Charlie {name: "Charlie Sheen"}) -[:ACTED_IN|DIRECTED*2]-(person:Person) return person.name
	5、可变长度关系的关系变量:当连接两个节点之间的长度是可变的,那么关系变量返回的将可能是一个关系列表。
	6、可变长度路径上的属性匹配:带有属性的可变长度关系,意味着路径上的所有关系都必须包含给定的属性值。
	7、零长度路径:可以通过指定可变长度路径的下界值为零,来实现两个变量指向同一个节点。例如:match ( wallstreet:Movie {title: "Wall Street"} ) -[*0..1]->(x) return x。
	8、命名路径:如果想返回或者需要对路径进行过滤,可以将路径赋值给一个变量。例如:match p = (michael { name: "Michael Douglas" } ) --> () return p。
	9、不指定方向匹配关系:可以不指定方向来匹配关系,Cypher将尝试匹配两个方向的关系。
15.1.4、最短路径
	1、单条最短路径:通过使用shortestPath函数很容易找到两个节点之间的最短路径,例如:match ( martin:Person { name:"Martin Sheen" } ), ( oliver:Person { name:"Oliver Ston" } ) , p=shortestPath( (martin) -[*..15]-(oliver) )
	2、带断言的最短路径:match ( charlie:Person { name:"Charlie Sheen" } ), ( martin:Person { name:"Martin Sheen" } ) , p=shortestPath( (charlie) -[*]-(martin) ) where none (r in rels(p) where type(r)="FATHER") return p 。rels(p)函数返回路径p中的所有关系。
	3、所有最短路径:找到两个节点之间的所有最短路径。例如:match ( martin:Person { name:"Martin Sheen" } ), ( oliver:Person { name:"Oliver Ston" } ) , p=allShortestPaths( (martin) -[*]-(oliver) )
15.1.5、通过id查询节点或关系
	1、通过id查询节点:可以在断言中使用id()函数来根据id查询节点。例如:match (n) where id(n) = 0 return n
	2、通过id查询关系:match ()-[r]-() where id(r) = 0 return r (可以但不推荐)
	3、通过id查询多个节点:通过id查询多个节点的时候,可以将id放到IN语句中。例如:match (n) where id(n) in [0,3,5] return n
15.2、optional_match语句
用于搜索模式中描述的匹配项,对找不到的项用null代替。
15.2.1、可选关系:如果某个关系是可选的,可使用optional_match。如果关系存在就返回,否则在相应的地方返回null。例如:match (a:Movie { title: "Wall Street" }) optional match (a)-->(x) return x。
15.2.2、可选元素的属性:如果可选的元素为null,那么该元素的属性也返回null。例如:match (a:Movie { title: "Wall Street" }) optional match (a)-->(x) return x, x.name。
15.2.3、可选关系类型:可在查询中指定可选的关系类型。例如:match (a:Movie { title: "Wall Street" }) optional match (a)-[r:ACTED_IN]->() return r。
15.3、where语句
WHERE在MATCH或者OPTINAL MATCH语句中添加约束,或者与WITH一起使用来过滤结果。
15.3.1、基本使用
	1、布尔运算:match (n) where n.name="Peter" or (n.age<30 and n.name="Tobias") return n。
	2、节点标签的过滤:match (n) where n:Swedish return n。
	3、节点属性的过滤:match (n) where n.age<30  return n。
	4、关系属性的过滤:match (n) -[k:KNOWS]->(f) where k.since<2000 return f。
	5、动态节点属性过滤:以方括号语法的形式使用动态计算的值来过滤属性。例如:match (n) where n[toLower($prop)] < 30 return n   参数为:{"prop": "AGE"}。
	6、属性存在性检查:可以使用exists()检查节点或者关系的某个属性是否存在。match (n) where exists(n.belt) return n。
15.3.2、字符串匹配
	可以用START WITH和ENDS WITH来匹配字符串的开始和结尾。如果不关心所匹配字符串的位置,可以用CONTAINS,匹配是区分大小写的。
	1、匹配字符串的开始:match (n) where n.name starts with "Pet" return n。
	2、匹配字符串的结尾:match (n) where n.name ends with "ter" return n。
	3、字符串包含:match (n) where n.name contains "ete" return n。
	4、字符串反向匹配:match (n) where not n.name ends with "s" return n。
15.3.3、正则表达式
	Cypher支持正则表达式过滤。正则表达式的语法继承来自Java正则表达式。它支持字符串如何匹配标记,包括不区分大小写(?i)、多行(?m)和单行(?s)。标记放在正则表达式的开头,例如MATCH (n) WHERE n.name =~ '(?i)Lon.*' RETURN n将返回名字为London和LonDoN的节点。
	1、正则表达式:match (n) where n.name =~  "Tob.*" return n。
	2、正则表达式中的转义字符:match (n) where n.address =~  "Sweden\\/Malmo" return n。
	3、正则表达式的非大小写敏感:match (n) where n.name =~  "(?i)ANDR.*" return n
15.3.4、在WHERE中使用路径模式
	1、模式过滤:模式是返回一个路径列表的表达式。列表表达式也是一种断言,空列表代表false,非空列表代表true。因此,模式不仅仅是一种表达式,同时也是一种断言。模式的局限性在于只能在单条路径中表达它,不能像在MATCH语句中那样使用逗号分隔多条路径,但可以通过AND组合多个模式。例如:match {tobias {name:"Tobias"}}, (others) where others.name in ["Andres", "Peter"] and (tobias)<--(others) return others。
	2、模式中的NOT过滤:match (persons), (peter {name: "Peter"}) where not (persons)-->(peter) return persons。
	3、模式中的属性过滤:match (n) where (n)-[:KNOWS]-({ name:"Tobias" }) return n。
	4、关系类型过滤:match (n)-[r]-() where n.name="Andres" and type(r) =~ "K.*" return r。
	5、在WHERE中使用简单存在子查询:match (person:Person) where exists ( match (person)-[:HAS_DOG]->(:Dog) ) return person.name as name。
	6、嵌套存在子查询:match (person:Person) where exists ( match (person)-[:HAS_DOG]->(:Dog) where exists ( match (dog)-[:HAS_TOY]->(toy:Toy) where toy.name="Banana" )) return person.name as name。
15.3.5、列表
	IN运算符:可以使用IN运算符检查列表中是否存在某个元素。
15.3.6、不存在的属性和值
	如果属性不存在,对它的判断默认返回false。对于不存在的属性值则当作null。
	1、属性不存在默认为true的情况:如果要比较的属性存在,则可以与期望的值进行比较;如果不存在(IS NULL),则默认值为true。
	2、空值过滤:可以使用IS NULL和IS NOT NULL测试某个值或变量是否为null。
15.3.7、使用范围
	1、简单范围:可以使用不等运算符<、>=和>检查某个元素是否在指定的范围。
	2、范围的组合:可以将多个不等式组合成一个范围。例如:match (a) where a.name > "Andres" and a.name < "Tobias" return a。
15.4、start语句
提示:START语句应当仅用于访问遗留的索引。所有其他的情况,都应使用MATCH代替。
15.4.1、通过索引获取节点:
	1、通过索引搜索(Index Seek)获取节点:当采用索引搜索查找开始点时,可以使用node:index-name(key = "value")。在本例中存在一个名为nodes的节点索引。例如:start n = node:nodes(name="A") return n。
	2、通过索引查询(Index Query)获取节点:当采用复杂的Lucene查询来查找开始点时,语法为node:index-name("query")。这样就可以写出很高级的索引查询。例如:start n = node:nodes("name:A") return n。
15.4.2、通过索引获取关系:
	当采用索引搜索查找开始点时,可以使用relationship:index-name(key = "value")。例如:start r = relationship:rels(name="Andres") return r  (在本例中存在一个名为rels的关系索引)。
15.5、aggregation语句
Cypher支持使用聚合(Aggregation)来计算聚在一起的数据,类似SQL中的group by。聚合函数有多个输入值,然后基于它们计算出一个聚合值。
15.5.1、count:
	count用于计算行的数量。count有两种使用方式:count(*)用于计算匹配的行数,而count(<expression>)用于计算<expression>中非空值的数量。
	1、计算节点的数量:match (n { name:"A" }) --> (x) return n, count(*)。结果将返回起始节点及与之相连节点的数量。
	2、按组计算关系类型的数量:match (n { name: "A" }) -[r]->() return type(r), count(*)。结果将返回关系类型和关系组中的关系数量。
	3、计算实体:match (n { name:"A" }) --> (x) return n, count(x)。结果将返回与满足带有name属性值为A的节点相连的所有节点的数量。
	4、计算非空值的数量:match (n:Person)  return count(n.property)。结果将返回property属性非空的节点的数量。
15.5.2、统计:
	1、sum:可以通过聚合函数sum计算所有值之和(空值将被丢弃)。例:match (n:Person)  return sum(n.property)。
	2、avg:计算数值列的平均值。例:match (n:Person)  return avg(n.property)。
	3、percentileDisc:计算给定值在一个组中的百分位,取值从0.0~1.0。它使用舍入法,返回最接近百分位的值。例:match (n:Person)  return percentileDisc(n.property, 0.5)。
	4、percentileCont:计算给定值在一个组中的百分位,百分位的值从0.0~1.0。它采用线性插值的方法,在两个值之间计算一个加权平均数。例:match (n:Person) return percentileCont(n.property, 0.4).
	5、stdev:计算给定值在一个组中的标准偏差。它采用标准的two-pass方法,以N-1作为分母。当以部分样本作为无偏估计时,应使用stdev;当计算整个样本的标准偏差时,应使用stdevp。例:match (n) where n.name in ['A','B', 'C'] return stdev(n.property)。
	6、stdevp:计算给定值在一个组中的标准偏差。例:match (n) where n.name in ['A','B', 'C'] return stdevp(n.property)。
	7、max/min:查找数值列中的最大值/最小值。例:match (n:Person) return max( n.property)。
	8、collect:将所有的值收集起来放入一个列表。空值null将被忽略。例:match (n:Person) return collect(n.property)。
	9、distinct:所有的聚合函数都可以带有DISTINCT修饰符,它将去掉其中的重复值。例:match (a:Person { name:"A" })-->(b) return count(distinct b.eyes)
15.6、load csv语句
load csv语句用于从CSV文件中导入数据。
	● CSV文件的URL可以由FROM后面紧跟的任意表达式来指定。
	● LOAD CSV支持以gzip、Deflate和ZIP压缩的资源。
	● CSV文件可以存在数据库服务器上,通过file:///URL来访问。LOAD CSV也支持通过HTTPS、HTTP和FTP来访问CSV文件。
	● LOAD CSV支持HTTP重定向,但基于安全考虑,重定向时不能改变协议类型,比如从HTTPS重定向到HTTP。
15.5.1、文件URL的配置项
	1、dbms.security.allow_csv_import_from_file_urls:这个选项决定Cypher在使用LOAD CSV时是否支持使用fille:/// URL来加载数据。该URL唯一标识了数据库服务器文件系统上的文件。dbms.security.allow_csv_import_from_file_urls=false将完全禁止LOAD CSV访问文件系统。
	2、dbms.directories.import:设置LOAD CSV中file:/// URL中的根路径。这必须设置为数据库服务器上的文件系统的单个目录,它让所有的请求从file:///URL加载时都使用根路径的相对路径(类似UNIX下的chroot操作)。默认值是import,这是基于安全考虑阻止数据库访问标准的import之外的目录下的文件。将dbms.directories.import设置为空可以消除这个安全隐患,允许访问系统上的任何文件,但是不推荐这么做。
		文件URLs将相对于dbms.directories.import来解析。例如,一个典型的URL类似file:///myfile.csv或者file:///myproject/myfile.csv。
		● 如果dbms.directories.import设置的是默认值import,那么在LOAD CSV语句将分别从<NEO4J_HOME>/import/myfile.csv和<NEO4J_HOME>/import/myproject/myfile.csv中读取数据。
		● 如果设置为/data/csv,上面的LOAD CSV中的URL将分别从/data/csv/myfile.csv和/data/csv/myproject/myfile.csv中读取数据。
15.5.2、CSV文件格式
	● 字符编码为UTF-8。
	● 行结束符取决于具体的操作系统,如unix上为\n,windows上为\r\n。
	● 默认的字段终止符为“,”。
	● 字段终止符可以使用LOAD CSV中的FIELDTERMINATOR选项来修改。
	● CSV文件允许引号字符串,但读取数据的时候引号字符会被丢弃。
	● 字符串的引号字符为双引号“"”。
	● 转义字符为“\”。
15.5.3、从CSV文件导入数据
	1、不包含文件头的CSV文件
		用LOAD CSV把数据加载到查询语句中。然后使用正常的Cypher更新语句将数据写入到数据库中。例:load csv from "file:///test.csv" as line create (:Artist {name:line[1], year:line[2]})。
	2、包含文件头的CSV文件
		当导入的CSV文件包含文件头时,可以把每一行看作一个map,而不是字符串数组。例:load csv with headers from "file:///test.csv" as line create (:Artist {name:line.Name, year:line.Year})。
	3、自定义分隔符的CSV文件
		CSV文件的分隔符有时候不是逗号,而是其他分隔符。这时可以使用FIELDTERMINATOR来指定分隔符。例:load csv from "file:///test.csv" as line fieldterminator ";" create (:Artist {name:line[1], year:line[2]})。
	4、导入海量数据
		如果导入的CSV文件包含百万数量级的行,可以使用USING PERIODIC COMMIT来告诉Neo4j每导入一定数量行之后就提交(Commit)一次。这样可避免在事务过程中耗费大量的内存。默认情况下,每1000行会提交一次。例:using periodic commit load csv from "file:///test.csv" as line create (:Artist {name:line[1], year:line[2]})。
	5、设置提交频率
		可以设置提交的频率。例:using periodic commit 500 load csv from "file:///test.csv" as line create (:Artist {name:line[1], year:line[2]})。
	6、导入包含转义字符的数据
		当CSV文件中的字符串 "The ""Symbol""" 被加载到Neo4j中时,转义的双引号会被解释为一个普通的双引号,结果就是 "The "Symbol""。
15.7、create语句
用于创建图元素:节点和关系。
15.6.1、创建节点
	1、创建单个节点:create (n)。
	2、创建多个节点:create (n), (m)。
	3、创建带有标签的节点:create (n:Person)。
	4、创建带有多个标签的节点:create (n:Person:Swedish)。
	5、创建同时带有标签和属性的节点:create (n:Person { name:"Andres" })。
	6、返回创建的节点:create (n:Person { name:"Andres" }) return n。
15.6.2、创建关系
	1、创建两个节点之间的关系:match (a:Person), (b:Person) where a.name='Node A' and b.name='Node B' create(a)-[r:RELTYPE]->(b) return r。
	2、创建关系并设置属性:match (a:Person), (b:Person) where a.name='Node A' and b.name='Node B' create(a)-[r:RELTYPE { name: a.name+'<->'+b.name } ]->(b) return r。
15.6.3、创建路径
	创建一个完整路径:create p = (andres { name:'andres' })-[:WORKS_AT]->(neo)<-[:WORKS_AT]-(michael { name:'Michael' }) return p。
15.6.4、CREATE中使用参数
	可以使用map来创建图的实体。map中的所有键值对都会被设置到创建的关系或节点上:
		参数:{ “props”: { "name":"Andres", "positon":"Developer" }  }
		查询:create (n:Person $props) return n。
	用属性参数创建多个节点:通过使用一个Cypher的map数组,它将为每个map创建一个节点:
		参数:{ “props”:[ { "name":"Andres", "positon":"Developer" },  { "name":"Michael", "positon":"Developer" } ] }
		查询:unwind $props as map create (n) set n = map 。
15.8、merge语句
MERGE或者匹配已存在的节点并绑定到它,或者创建新的节点然后绑定到它。它有点像MATCH和CREATE的组合。通过这种方式可以确保你指定的某个数据存在数据库中。
当在整个模式上使用MERGE时,要么是整个模式匹配到,要么是整个模式被创建。MERGE不能部分地应用于模式,如果希望部分匹配,可以将模式拆分为多个MERGE语句。
15.8.1、MERGE节点
	1、合并带标签的节点
		merge ( robert:Critic ) return robert, labels(robert):因为没有包含Critic标签的节点,所以在数据库创建了新节点。
	2、合并带多个属性的单个节点
		merge ( charlie { name:"Charlie Sheen", age:10 } ) return charlie:在数据库创建了名为Charlie Sheen的新节点,因为没有匹配到所有属性都吻合的节点。
	3、合并同时指定标签和属性的节点
		merge ( michael:Person { name:"Michael Douglas" } ) return michael.name, michael.bornIn:匹配到Michael Douglas节点,同时返回它的name和bornIn属性。
	4.合并属性,过滤已存在节点,创建不存在节点
		match (person:Person) merge (city:City { name: person.bornIn }) return person.name, person.bornIn, city:创建了三个City节点,它们的name属性分别为New York、Ohio和New Jersey。尽管MATCH匹配的结果有三个节点的bornIn属性值都为New York,但只创建了一个New York节点。因为第一次匹配的时候,New York未匹配到,因此创建了一个。然后,新创建的New York被第二个和第三个匹配到了。
15.8.2、MERGE在CREATE和MATCH中的使用
	1、MERGE与CREATE搭配
		检查节点是否存在,如果不存在,则创建它并设置属性。
		merge (keanu:Person { name:"Keanu Reeves" }) on create set keanu.created = timestamp() return keanu.name, keanu.created。
	2、MERGE与MATCH搭配
		匹配节点,并在找到的节点上设置属性。
		merge (person:Person) on match set person.found = TRUE return person.name, person.found。
	3、MERGE与CREATE和MATCH同时使用。
		检查节点是否存在,如果不存在,则创建它并设置属性。
		merge (keanu:Person { name:"Keanu Reeves" }) on create set keanu.created = timestamp() on match set keanu.lastSeen=timestamp() return keanu.name, keanu.created,keanu.lastSeen。
	4、利用MERGE和MATCH设置多属性
		如果需要设置多个属性,将它们简单地以逗号分开即可。
		merge (person:Person) on match set person.found=TRUE,person.lastAccessed=timestamp() return person.found, person.lastAccessed。
15.8.3、MERGE关系
	1、合并多个关系
		当MERGE应用于整个模式时,要么全部匹配上,要么全部新创建。
		match (oliver:Person {name: 'Oliver Stone'}),(reiner:Person { name: 'Rob Reiner'}) merge (oliver)-[:DIRECTED]->(movie:Movie)<-[:ACTED IN]-(reiner) return movie。
		在本例中,Oliver Stone和Rob Reiner未一起工作过。当试图在其之间合并一个电影连接时,Neo4j不会使用任何已存在的电影,而是创建一个新的movie节点。
	2.合并无方向关系
		MERGE也可以用于合并无方向的关系。当创建关系时,它将选择一个任意的方向。
		match (oliver:Person {name: 'Oliver Stone'}),(charlie:Person { name: 'Charlie Sheen'}) merge (oliver)-[r:KNOWS]-(charlie) return r。
		因为Charlie Sheen和Oliver Stone相互不认识,所以MERGE查询将在他们之间创建一个KNOWS关系。创建的关系的方向是任意的。
	3、合并已存在两节点之间的关系
		MERGE可用于连接前面的MATCH和MERGE语句,在两个绑定的节点m和n上创建一个关系。m节点是MATCH语句返回的,而n节点是前面的MERGE语句创建或者匹配到的。
		match (person:Person) merge (city:City { name: person.bornIn }) merge (person)-[r:BORN_IN]->(city) return person.name, person.bornIn, city
		第二个MERGE在每个人和他的bornIn属性对应的城市之间创建了一个BORN_IN关系。Charlie Sheen、Rob Reiner和Oliver Stone与同一个城市节点(New York)都有一个BORIN_IN关系。
	4、合并一个已存在节点和一个合并的节点之间的关系
		MERGE能够同时创建一个新节点n和一个已存在节点m与n之间的关系。
		match (person:Person) merge (person)-[r:HAS_CHAUFFEUR]->(chauffeur:Chauffeur { name: person.chauffeurName }) return person.name, person.chauffeurName, chauffeur
15.8.4、用MERGE的唯一性约束
	当使用的模式涉及唯一性约束时,Cypher可以通过MERGE来防止获取相冲突的结果。在这种情况下,至多有一个节点匹配该模式。例如,给定两个唯一性约束:Person(id)和:Person(ssn),如果存在两个不同的节点分别是id为12和ssn为437或者只有一个节点有其中一个属性,那么MERGE (n:Person {id: 12, ssn: 437})这样的查询将失败。。
	1、唯一性约束与部分匹配
		当只有部分匹配时,使用唯一性约束合并将失败。
		merge (michael:Person {name: 'Michael Douglas', role: 'Gordon Gekko'}) return michael
		虽然存在Person名为 的匹配唯一节点Michael Douglas,但没有角色为 的唯一节点,Gordon Gekko因此MERGE匹配失败(没有唯一性约束时会新建,有唯一性约束时无法新建)。
	2、唯一性约束与匹配冲突
		当有匹配的冲突结果时,使用MERGE唯一性约束将失败。
		merge (oliver:Person { name:'Oliver Stone', role:'Gordon Gekko'}) return oliver
		错误消息:Merge did not find a matching node oliver and can not create a new node due toconflicts with existing unique nodes。
15.8.5、使用map参数
	MERGE不支持像CREATE节点时那样使用map参数。要在MERGE中使用map参数,需要显式地使用希望用到的属性。
	参数:{ "param": { "name": "Keanu Reeves", "role": "Neo" } }
	查询:merge (person:Person(name:$param.name, role:$param.role)) return person.name,person.role
15.9、set语句
SET语句用于更新节点的标签以及节点和关系的属性。SET可以使用map中的参数来设置属性。
设置节点的标签是幂等性操作,即如果试图设置一个已经存在的标签到节点上,则什么也不会发生。查询统计会自己判断是否需要处理。
15.9.1、设置属性
	match (n { name: 'Andres' }) set n.surname = 'Taylor' return n
	match (n { name: 'Andres' }) set n.surname = 'Taylor', n.position = 'Developer' return n
15.9.2、删除属性(可以但不通用,通用方案是使用remove)
	match (n { name: 'Andres' }) set n.name = null return n
15.9.3、在节点和关系间复制属性
	match (at { name: 'Andres' }), (pn { name: 'Peter' })  set at = pn return at, pn
15.9.4、从map中添加属性
	当用map来设置属性时,可以使用+=形式的SET,用于只添加属性,而不删除图元素中已存在的属性。
	match (peter {name:'Peter'}) set peter +=(hungry:TRUE, position:'Entrepreneur')
15.9.5、使用参数设置属性
	参数: { "surname": "Taylor" }
	查询:match (n { name: "Andres" }) set n.surname = $surname return n
15.9.6、使用一个参数设置所有属性
	参数:{ "props": { "name":"Andres", "position": "Developer" } }
	查询: match (n { name:"Andres" }) set n=$props return n
15.9.7、设置节点的标签
	match (n { name: "stefan" }) set n:German return n
	match (n { name: "Emil" }) set n:Swedish:Bossman return n
15.10、delete语句
delete语句用于删除图元素(节点、关系或路径)。
不能只删除节点,而不删除与之相连的关系。要么显式地删除对应的关系,要么使用detach delete。
15.9.1、删除单个节点
	match (n:Useless) delete n
15.9.2、删除所有节点和关系
	match (n) detach delete n
15.9.3、删除一个节点及其所有的关系
	match (n { name: "Andres" }) detach delete n
15.11、remove语句
remove语句用于删除图元素的属性和标签。
删除节点的标签是幂等性操作。如果删除一个节点的不存在的标签,什么也不会发生。查询统计会自己判断是否需要处理。
15.11.1、删除一个属性
	Neo4j不允许属性存储空值null。如果属性的值不存在,那么节点或者关系中的属性将被删除。这也可以通过remove来删除。
	match ( andres { name:"Andres" }) remove andres.age return andres
15.11.2、删除节点的一个标签
	match (n { name: "Peter" }) remove n:German return n
15.11.3、删除节点的多个标签
	match (n { name: "Peter" }) remove n:German:Swedish return n
15.12、foreach语句
foreach语句用于更新列表中的数据,或者来自路径的组件,或者来自聚合的结果。
15.11.1、标记路径上的所有节点
	match p = (begin)-[*]-(end) where begin.name="A" and end.name="D" foreach (n in nodes(p)) | set n.marked=True
15.11.2、从列表中创建
	match (a:Person {name:"A"}) foreach (name in [ "Mike", "Carl", "Bruce" ]) create (a)-[:FRIEND]->(:Person { name: name})
15.13、create unique语句
create unique作用是匹配所能匹配得上的,创建不存在的。create unique尽可能地减少对图的改变,充分利用已有的图。create unique假设模式是唯一性的,如果有多个匹配的子图可以找到,则此时将会报错。
15.11.1、创建唯一节点
	1、创建未匹配到的节点
		match (root: { name:"root" }) create unique (root)-[:LOVES]-(someone) return someone
		root节点没有任何LOVES关系。因此,创建了一个节点及其与root节点的LOVES关系。
	2、用含值的模式创建节点
		match (root: { name:"root" }) create unique (root)-[:X]-(leaf { name:"D}) return leaf
		没有与root节点相连的name为D的节点,所以创建一个新的节点来匹配该模式。
	3、创建未匹配到带标签的节点
		如果描述的模式需要一个带标签的节点,而数据库中没有带给定标签的节点,Cypher将创建一个新的节点。
		match (a { name:"a" }) create unique (a)-[:KNOWS]-(c:blue) return c
		与A节点相连的KNOWS关系有一个C节点,但C节点没有blue标签,那么将创建一个带有blue标签的节点和从A到它的KNOWS关系。
15.11.2、创建唯一关系
	1、创建未匹配到的关系
		match (lft { name:"A" }), (rgt) where rgt.name in ["B", "C"] create unique (lft)-[r:KNOWS]->(rgt) return r
		匹配一个左节点和两个右节点之间的关系。其中一个关系已存在,因此能匹配到,然后创建了不存在的关系。
	2、用含值的模式创建关系
		match (root { name:"root" }) create unique (root)-[r:X { since:"forever" }]-() return r
		本例中希望关系有一个值,因为没有这样的关系匹配到,因此创建了一个新节点和关系。注意,因为不关心创建的节点,所以没有对该节点命名。
15.11.3、描述复杂模式
	match (root { name:"root" }) create unique (root)-[:FOO]->(x), (root)-[:BAR]-(x) return x
	本例中的模式使用了两条用逗号分隔的路径。
15.14、return语句
return语句定义了查询结果集中返回的内容。
提示:如果只需要属性值,就要尽量避免返回整个节点或关系,这样有助于提高性能。
15.14.1、返回节点
	match (n {name: "B"}) return n
15.14.2、返回关系
	match (n { name:"A" })-[r:KNOWS]->(c) return r
15.14.3、返回属性
	match (n {name: "B"}) return n.name
15.14.4、返回所有元素
	match p = (a { name:"A" })-[r]-(b) return *
	返回了两个节点、关系和路径。
15.14.5、列别名
	match (a { name:"A" }) return a.age as SomethingTotallyDifferent
15.14.6、可选属性
	如果某个属性可能存在,也可能不存在。这时,依然可以正常地去查询,对于不存在的属性,Cypher则返回null。
	match (n) return n.age
15.14.7、其他表达式
	任何表达式都可以作为返回项,如字面值、断言、属性、函数和任何其他表达式。
	match (a { name:"A" }) return a.age> 30, "i'm a literal", (a)-->()
15.14.8、唯一性结果
	DISTINCT用于仅仅获取结果集中所依赖列的唯一行。
	match (a { name:"A" }) -->(b) return distinct b
15.15、order by语句
order by是紧跟RETURN或者WITH的子句,它指定了输出的结果应该如何排序。
提示:不能对节点或关系进行排序,只能对它们的属性进行排序。ORDER BY依赖值的比较来排序。
15.14.1、根据属性对节点进行排序
	match (n) return n order by n.name
15.14.2、根据多个属性对节点进行排序
	match (n) return n order by n.name, n.age
15.14.3、节点降序排列
	match (n) return n order by n.name desc
15.14.4、空值的排序
	当结果集中包含null值时,对于升序排列,null总是在结果集的末尾。而对于降序排序,null值总是排在最前面。
15.16、limit语句
limit语句限制输出的行数。limit可接受结果为正整数的任意表达式,但表达式不能引用节点或者关系。
	match (n) return n order by n.name limit 3
	match (n) return n order by n.name limit toInt(3*rand())+1
15.17、skip语句
skip语句定义了从哪行开始返回结果。使用skip可以跳过开始的一部分结果。
	match (n) return n order by n.name skip 1 limit 2
15.18、with语句
with语句将分段的查询部分连接在一起,查询结果从一部分以管道形式传递给另外一部分作为开始点。
15.18.1、过滤聚合函数结果
	聚合的结果必须通过WITH语句传递才能进行过滤。
	match (david { name:"David" })--(otherPerson)-->() with otherPerson, count(*) as foaf where foaf >1 return otherPerson 
15.18.2、在collect前对结果排序
	match (n) with n order by n.name desc limit 3 return collect(n.name)
15.18.3、限制路径搜索的分支
	可以限制匹配路径的数量,然后以这些路径为基础再做任何类似的有限制条件的搜索。
	match (n { name:"Andres" })--(m) with m order by m.name desc limit 1 match(m) --(o) return o.name
15.19、unwind语句
unwind语句将一个列表展开为一个行的序列。用unwind可以将任何列表转为单独的行。这些列表可以参数的形式传入。
15.19.1、UNIND列表
	unwind [1, 2, 3] as x return x
15.19.2、创建唯一列表
	with [1, 1, 2, 2] as coll unwind coll as x with distinct x return collect(x) as set
15.19.3、从列表参数创建节点
	参数: { "events": [ { "year":2014, "id": 1 }, { "year": 2014, "id":2 } ] }
	查询:unwind $events as event merge (y:Year { year: event.year}) merge (y)<-[:IN]-(e:Event { id:event.id }) return e.id as x order by x
15.20、union语句
union语句用于将多个查询结果组合起来。使用union组合查询的结果时,所有查询到的列的名称和数量必须完全一致。使用union all会包含所有结果行,而用union组合时,会移除结果集中的重复行。
15.20.1、组合两个查询
	match (n:Actor) return n.name as name union all match(n:Movie) return n.title as name
15.20.2、组合两个查询并移除重复值
	match (n:Actor) return n.name as name union match(n:Movie) return n.title as name
15.21、call语句
call语句用于调用数据库中的过程(Procedure)。使用CALL语句调用过程时,需要指定所需要的参数。可以通过在过程名的后面使用逗号分隔的列表来显式地指定,也可以使用查询参数来作为过程调用的实参。后者仅适用于在单独的过程调用中作为参数,即整个查询语句只包含一个单一的call调用。
大多数的过程返回固定列的记录流,类似于Cypher查询返回的记录流。yield子句用于显式地选择返回结果集中的哪些部分并绑定到一个变量以供后续的查询引用。在一个更大的查询内部,过程调用返回的结果可以显式地使用yield引入一个where子句来过滤结果。
Neo4j支持void过程。void过程既没有声明任何结果字段,也不返回任何结果记录。调用VOID过程可能有一个副作用,就是它既不允许也不需要使用yield。在一个大的查询中调用void过程,就像with *在记录流的作用那样简单地传递输入的每一个结果。
15.21.1、调用过程
	call db.labels
15.21.2、使用命名空间和名字调用过程
	call `db`.`labels`
15.21.3、使用字面值参数调用过程
	call org.neo4j.procedure.example.addNodeToIndex("user", 0, "name")
15.21.4、使用参数作为实参调用过程
	参数:{ "setting": "server.bolt.enabled", "value": "true" }
	查询:call dbms.checkConfigValue($setting, $value)
15.21.5、混合使用字面值和参数调用过程
	参数:{ "node": 0 }
	查询:call org.neo4j.procedure.example.addNodeToIndex("user", $node, "name")
15.21.6、使用字面值和默认实参调用过程
	call org.neo4j.procedure.example.addNodeToIndex("user", 0)
15.21.7、在复杂查询中调用过程
	call db.labels() yield label return count(label) as numLabels
15.21.8、调用过程并过滤结果
	call db.labels() yield label where label contains "User" return count(label) as numLabels
15.21.9、在复杂查询中调用过程并重命名结果
	call db.propertyKeys() yield propertyKey as prop match(n) where n[prop] is not null return prop, count(n) as numNodes
16、函数
16.1、断言函数
断言(Predicate)函数是对给定的输入返回true或者false的布尔函数,它们主要用于查询where的部分过滤子图。
16.1.1、all()
	判断是否一个断言适用于列表中的所有元素。
	语法:all(variable IN list WHERE predicate)
	● list:返回列表的表达式。
	● variable:用于断言中的变量。
	● predicate:用于测试列表中所有元素的断言。
	例:match p = (a)-[*1..3]->(b) where a.name= "Alice" and b.name="Daniel" and all(x in nodes(p) where x.age > 30) return p
16.1.2、any()
	判断是否一个断言至少适用于列表中的一个元素。
	语法:any(variable IN list WHERE predicate)
	● list:返回列表的表达式。
	● list:返回列表的表达式。
	● predicate:用于测试列表中所有元素的断言。
	例:match (a) where a.name= "Eskil"  and any(x in a.array where x="one") return a
16.1.3、none()
	如果断言不适用于列表中的任何元素,则返回true。
	语法:none(variable IN list WHERE predicate)
	● list:返回列表的表达式。
	● variable:用于断言中的变量。
	● predicate:用于测试列表中所有元素的断言。
	例:match p = (a)-[*1..3]->(b) where a.name= "Alice" and none(x in nodes(p) where x.age = 25) return p
16.1.4、single()
	如果断言只适用于列表中的某一个元素,则返回true。
	语法:single(variable IN list WHERE predicate)
	● list:返回列表的表达式。
	● variable:用于断言中的变量。
	● predicate:用于测试列表中所有元素的断言。
	例:match p = (n)-->(b) where n.name="Alice" and single(var in nodes(p) where var.eyes="blue") return p
16.1.5、exists()
	如果数据库中存在该模式或者节点中存在该属性时,就返回true。
	语法:exists(pattern-or-property)
	● pattern-or-property:模式或者属性(以variable.prop的形式)。
	例:match (n) where exists (n.name) return n.name as name, exists ((n)-[:MARRIED]->()) as is_married
16.2、标量函数
标量(Scalar)函数返回一个单值。
16.2.1、size()
	使用size()返回表中元素的个数。
	语法:size(list)
	● list:返回列表的表达式。
	例:return size([ "Alice", "Bob" ]) as col
16.2.2、模式表达式的size
	参数是一个模式表达式匹配到的查询结果集。计算的是结果集元素的个数,而不是表达式本身的长度。
	语法:size(pattern expression)
	● pattern expression:返回列表的模式表达式。
	例:match (a) where a.name="Alice" return size( (a)-->()-->() ) as fof
16.2.3、length()
	使用length()函数返回路径的长度。
	语法:length(path)
	● path:返回路径的表达式。
	例:match p = (a)-->(b)-->(c) where a.name="Alice" return length(p)
16.2.4、字符串的长度
	语法:length(string)
	● string:返回字符串的表达式。
	例:match (a) where length(a.name) > 6 return length(a.name)
16.2.5、type()
	返回字符串代表的关系类型。
	语法:type(relationship)
	● relationship:一个关系。
	例:match (n)-[r]->() where n.name="Alice" return type(r)
16.2.6、id()
	返回关系或者节点的id。
	语法:id(property-container)
	● property-container:一个节点或者关系。
	例:match (a) return id(a)
16.2.7、coalesce()
	返回表达式列表中的第一个非空的值。如果所有的实参都为空,则返回null。
	语法:coalesce(expression [, expression]*)
	● expression:表达式,可能返回null。
	例:match (a) where a.name="Alice" return coalesce(a.hairColor, a.eyes)
16.2.8、head()
	head()返回列表中的第一个元素。
	语法:head(expression)
	● expression:返回列表的表达式。
	例:match (a) where a.name="Eskil" return a.array, head(a.array)
16.2.9、last()
	last()返回列表中的最后一个元素。
	语法:last(expression)
	● expression:返回列表的表达式。
	例:match (a) where a.name="Eskil" return a.array, last(a.array)
16.2.10、timestamp()
	timestamp()返回当前时间与1970年1月1日午夜之间的差值,单位以毫秒计算。它在整个查询中始终返回同一个值,即使是在一个运行时间很长的查询中。
	语法:timestamp()
16.2.11、startNode()
	startNode()返回关系的开始节点。
	语法:startNode(relationship)
	● relationship:返回关系的表达式。
	例:match (x:foo)-[r]-() return startNode(r)
16.2.12、endNode()
	endNode()返回关系的结束节点。
	语法:endNode(relationship)
	● relationship:返回关系的表达式。
	例:match (x:foo)-[r]-() return endNode(r)
16.2.13、properties()
	properties()将实参转为属性值的map。如果实参是一个节点或者关系,返回的就是节点或关系的属性的map;如果实参已经是一个map了,那么原样返回结果。
	语法:properties(expression)
	● expression:返回节点、关系或者map的表达式。
	例:create (p:Person { name:"Stefan", city:"Berlin" }) return properties(p)
16.2.14、toInteger()
	toInteger将实参转换为一个整数。字符串会被解析为一个整数,如果解析失败,将返回null。浮点数将被强制转换为整数。
	语法:toInteger(expression)
	● expression:返回任意值的表达式。
	例:return toInteger("42")
16.2.15、toFloat()
	toFloat()将实参转换为浮点数。字符串会被解析为一个浮点数,如果解析失败,将返回null。整数将被强制转换为浮点数。
	语法:toFloat(expression)
	● expression:返回任意值的表达式。
	例:return toInteger("42.5")
16.3、列表函数
列表(List)函数返回列表中的元素,如路径中的节点等。
16.3.1、nodes()
	返回一条路径中的所有节点。
	语法:nodes(path)
	● path:一条路径。
	例:match p=(a)--(b)--(c) where a.name="James Thompson" and c.name="Jessica Thompson" return nodes(p)
16.3.2、relationships()
	返回一条路径中的所有关系。	
	语法:relationships(path)
	● path:一条路径。
	例:match p=(a)--(b)--(c) where a.name="James Thompson" and c.name="Jessica Thompson" return relationships(p)
16.3.3、labels()
	以字符串列表的形式返回一个节点的所有标签。
	语法:labels(node)
	● node:返回单个节点的任意表达式。
	例:match (a) where a.name="Alice" return labels(a)
16.3.4、keys()
	以字符串列表的形式返回一个节点、关系或者map的所有属性的名称。
	语法:keys(property-container)
	● property-container:一个节点、关系或者字面值的map。
	例:match (a) where a.name="Alice" return keys(a)
16.3.5、extract()(不可用)
	可以使用extract()从节点或关系列表中返回单个属性或者某个函数的值。它将遍历整个列表,针对列表中的每个元素运行一个表达式,然后以列表的形式返回这些结果。
	语法:extract(variable IN list | expression)
	● list:返回列表的表达式。
	● variable:引用list中元素的变量,它在expression中会用到。
	● expression:针对列表中每个元素所运行的表达式,并产生一个结果列表。
	例:match p=(a)-->(b)-->(c) where a.name="Alice" and b.name="Bob" and c.name="Daniel" return extract(n in nodes(p) | n.age) as extracted
16.3.6、filter()  (不可用)
	filter()返回列表中满足断言要求的所有元素。
	语法:filter(variable IN list WHERE predicate)
	● list:返回列表的表达式。
	● variable:断言中引用列表元素所用到的变量。
	● predicate:针对列表中每个元素进行测试的断言。
	例:match (a) where a.name = "Eskil" return a.array, filter(x in a.array where size(x)=3)
16.3.7、tail()
	tail()返回列表中除了首元素之外的所有元素。
	语法:tail(expression)
	● expression:返回某个类型列表的表达式。
	例:with [1, 2, 3, 4, 5] as nums return tail(nums) as remaining
16.3.8、range()
	range()返回某个范围内的数值。值之间的默认步长为1,范围包含起始边界值。
	语法:range(start, end [, step])
	● start:起点数值的表达式。
	● end:结束数值的表达式。
	● step:数值间隔的步长。
	例:return range(1,10), range(1,10,2)
16.3.9、reduce()
	可以用reduce()对列表中的每个元素执行一个表达式,将表达式结果存入一个累加器。
	语法:reduce(accumulator = initial, variable IN list | expression)
	● accmulator:用于累加每次迭代的部分结果。
	● initial:累加器的初始值。
	● list:列表。
	● variable:引用列表中的每个元素的变量。
	● expression:针对列表中每个元素执行的表达式。
	例:with [1, 2, 3, 4, 5] as numbers return reduce(sum = 0, number IN numbers | sum + number) as total
16.4、数学函数
16.3.1、数值函数
	1、abs():返回数值的绝对值。
		语法:abs(expression)
		● expression:数值表达式。
	2、ceil():返回大于或等于实参的最小整数。
		语法:ceil(expression)
		● expression:数值表达式。
	3、floor():返回小于等于表达式的最大的整数。
		语法:floor(expression)
		● expression:数值表达式。
	4、round():返回距离表达式值最近的整数。
		语法:round(expression)
		● expression:数值表达式。
	5、sign():返回一个数值的正负。如果值为零,则返回0;如果值为负数,则返回-1;如果值为正数,则返回1。
		语法:sign(expression)
		● expression:数值表达式。
	6、rand():返回[0, 1)之间的一个随机数,返回的数值在整个区间遵循均匀分布。
		语法:rand()
16.3.2、对数函数
	1、log():返回表达式的自然对数。
		语法:log(expression)
		● expression:数值表达式。
	2、log10():返回表达式的常用对数(以10为底)。
		语法:log10(expression)
		● expression:数值表达式。
	3、exp():返回e^n,这里e是自然对数的底,n是表达式的实参值。
		语法:exp(expression)
		● expression:数值表达式。
	4、e():返回自然对数的底,即e。
		语法:e()
	5、sqrt():返回数值的平方根。
		语法:sqrt(expression)
		● expression:数值表达式。
16.3.3、三角函数
	1、sin():返回表达式的正弦函数值。
		语法:sin(expression)
		● expression:一个表示角的弧度的数值表达式。
	2、cos():返回表达式的余弦函数值。
		语法:cos(expression)
		● expression:一个表示角弧度的数值表达式。
	3、tan():返回表达式的正切值。
		语法:tan(expression)
		● expression:一个表示角弧度的数值表达式。
	4、cot():返回表达式的余切值。
		语法:cot(expression)
		● expression:一个表示角弧度的数值表达式。
	5、asin():返回表达式的反正弦值。
		语法:asin(expression)
		● expression:一个表示角弧度的数值表达式。
	6、acos():返回表达式的反余弦值。
		语法:acos(expression)
		● expression:一个表示角弧度的数值表达式。
	7、atan():返回表达式的反正切值。
		语法:atan(expression)
		● expression:一个表示角弧度的数值表达式。
	8、atan2():返回方位角,也可以理解为计算复数x+yi的幅角。
		语法:atan2(expression1, expression2)
		● expression1:表示复数x部分的数值表达式。
		● expression2:表示复数y部分的数值表达式。
	9、pi():返回常数pi的数值。
		语法:pi()
	10、degrees():将弧度转为度。
		语法:degrees(expression)
		● expression:一个表示角弧度的数值表达式。
	11、radians():将度转为弧度。
		语法:radians(expression)
		● expression:一个表示角度数的数值表达式。
	12、haversin():返回表达式的半正矢值。
		语法:haversin(expression)
		● expression:一个表示角弧度的数值表达式。
16.5、字符串函数
16.5.1、replace():返回被替换字符串替换后的字符串,它会替换所有出现过的字符串。
	语法:replace(original, search, replace)
	● original:原字符串。
	● search:期望被替换的字符串。
	● search:期望被替换的字符串。
	例:return replace("Hello, world", "H", "h")
16.5.2、substring():返回原字符串的子串。它带有一个0为开始的索引值和长度作为参数。如果长度省略了,那么它返回从索引开始到结束的子字符串。
	语法:substring(original, start [, length])
	● original:原字符串。
	● start:子串的开始位置。
	● length:子串的长度。
	例:return substring("Hello, World", 0, 5)
16.5.3、left():返回原字符串左边指定长度的子串。
	语法:left(original, length)
	● original:原字符串。
	● length:左边子字符串的长度。
	例:return left("Hello, World", 5)
16.5.4、right():返回原字符串右边的指定长度的子字符串。
	语法:right(original, length)
	● original:原字符串。
	● length:右边子字符串的长度。
	例:return right("Hello, World", 5)
16.5.5、ltrim():返回原字符串移除左侧的空白字符后的字符串。
	语法:ltrim(original)
	● original:原字符串。
	例:return ltrim("  Hello, World  ")
16.5.6、rtrim():返回原字符串移除右侧空白字符后的字符串。
	语法:rtrim(original)
	● original:原字符串。
	例:return rtrim("  Hello, World  ")
16.5.7、trim():返回原字符串移除两侧的空白字符之后的字符串。
	语法:trim(original)
	● original:原字符串。
	例:return trim("  Hello, World  ")
16.5.8、lower():以小写的形式返回原字符串。(不可用)
	语法:lower(original)
	● original:原字符串。
16.5.9、upper():以大写的形式返回原字符串。(不可用)
	语法:upper(original)
	● original:原字符串。
16.5.10、split():返回以指定模式分隔后的字符串序列。
	语法:split(original, splitPattern)
	● original:原字符串。
	● splitPattern:分割字符串。
	例:return split("one,two",",")
16.5.11、reverse():返回原字符串的倒序字符串。
	语法:reverse(original)
	● original:原字符串。
	例:return reverse("hello world")
16.5.12、toString():将实参转换为字符串。它将整型、浮点型和布尔型转换为字符串。如果实参为字符串,则按原样返回。
	语法:toString(expression)
	● expression:返回数值、布尔或者字符串的表达式。
	例:return tostring(10086)
16.6、自定义函数
自定义函数用Java语言编写,可部署到数据库中,调用方式与其他Cypher函数一样。
16.6.1、调用自定义函数
	例:match (n) return org.neo4j.function.example.join(collect(n.name))
16.6.2、编写自定义函数
	自定义函数的编写类似于过程的创建,但它采用@UserFunction注解,并且只返回一个单值。有效的输出类型包括long、Long、double、Double、boolean、Boolean、String、Node、Relationship、Path、Map<String、Object>或者List<T>,这里的T可以是任意支持的类型。
	例:

在这里插入图片描述

17、索引
数据库索引是为了提升搜索效率而创建的某些数据的特殊冗余,以额外的存储空间和写操作为代价。确定索引数据的范围,是一项重要且有一定难度的工作。Neo4j的索引由DBMS管理和更新,一旦创建并生效,Neo4j将自动选择并使用。
17.1、索引类型
● b树索引(b-tree):Cypher可以为拥有指定标签的所有节点,或拥有指定关系类型的所有关系,建立基于单个或多个属性的b树索引。基于给定标签或关系类型在单个属性上创建的索引称为单属性索引。基于给定标签或关系类型在多个属性上创建的索引称为复合索引。
● 全文索引(fulltext):全文索引是基于节点和关系的字符串型属性建立的索引,可以用来对属性值进行匹配查询,由Apache Lucene索引和搜索库提供支持。
● 查找索引(lookup):查找索引只依赖节点标签或关系类型,不考虑属性。
● 文本索引(text):文本索引是一种单属性索引,但只能用于字符串类型的属性。如果节点的标签或关系的关系类型不是字符串型,则这些节点和关系就不能被索引。
17.2、索引使用建议
● 创建索引时明确其名称。如果没有命名,则数据库会为索引会自动生成名称。
● 索引的名称必须在索引和约束中同时保持唯一。
● 默认情况下,索引不能重复创建,两次创建相同的索引会报错。使用IF NOT EXISTS子句可以避免这种报错。
17.3、复合索引
复合b树索引同单属性b树索引一样,能支持所有的判断式:
● 等值判断:n.prop = value。
● 列表成员判断:n.prop IN list。
● 存在判断:n.prop IS NOT NULL。
● 范围搜索:n.prop > value。
● 前缀判断:STARTS WITH。
● 后缀判断:ENDS WITH。
● 子串搜索:CONTAINS。
判断式可能会被执行计划(Execution Plan)优化为存在检查和过滤器,为了避免这种情况,判断式需要遵循以下限制规则:
● 如果有任何等值检查和列表成员判断,它们需要用于索引定义的第一个属性。
● 最多可以有一个范围判断或前缀判断。
● 可以有任意数量的存在判断式。
● 范围判断、前缀判断或存在判断后的判断式必须为存在判断。而前缀判断和子串判断总是被调整为存在判断式和过滤器,因此其后的所有判断式也被调整为存在判断式。
17.4、创建索引
17.4.1、b树索引
	1、单值索引
		为某个标签的所有节点创建带命名的单属性b树索引:
			create index index_name for (n:Label) in (n.property)
		为特定类型的所有关系创建带命名的单属性b树索引:
			create index index_name for ()-[r:TYPE]-() on (r.property)
		如果不知道索引是否已经存在,可以使用IF NOT EXISTS子句,如果已经存在模式和类型相同、或者名称相同、或者两者都相同的索引,则索引不会重复创建。
			create index node_index_name if not exists for (n:Person) on (n.surname)
	2、复合索引
		为特定标签的所有节点创建带命名的多属性b树索引,即节点复合索引:
			create index index_name for (n:Label) in (n.prop1, ... , n.propN)
			节点复合索引仅包含具有指定标签且拥有索引相关所有属性的节点。
		为特定关系类型的所有关系创建带命名的多属性b树索引,即关系复合索引:
			create index index_name for ()-[r:TYPE]-() on (r.prop1, ... , r.propN)
			关系复合索引仅包含具有指定类型且拥有索引相关所有属性的关系。
17.4.2、lookup索引
	为一个或多个标签的所有节点创建命名的标记查找索引:
		create lookup index index_name for (n) on each labels(n)
	为任意关系类型的所有关系创建命名标记查找索引:
		create lookup index index_name for ()-[r]-() on each type(r)
17.4.3、文本索引
	文本索引仅支持字符串值,且不支持多个属性。
	为特定标签的所有节点创建单属性的文本索引:
		create text index index_name for (n:Label) on (n.property)
	为特定关系类型的所有关系创建单属性的文本索引:
		create text index index_name for ()-[r:TYPE]-() on (r.property)
	如果不知道索引是否已经存在,可以使用IF NOT EXISTS子句。
		create text index node_index_name if not exists for (n:Person) on (n.nickname)
17.5、列出索引
通过命令show indexes可以列出已有的索引。
例:show LOOKUP indexes where entityType="NODE"
17.6、删除索引
通过命令DROP INDEX index_name,可以将指定名称的索引删除掉。
	drop index missing_index_name if exists
此命令可以删除任何类型的索引,但不能删除包含在约束中的索引。索引名称可以通过SHOW INDEXES命令查询。
17.7、全文索引
全文索引是基于节点和关系的字符串型属性建立的索引,可以用来对属性值进行匹配查询,由Apache Lucene索引和搜索库提供支持。B树索引只能对字符串进行精确匹配或前缀匹配,而全文索引可以对被索引的字符串值进行分词(tokenize),因此可以匹配字符串中任何位置的元素(term)。字符串如何被分词和分解为元素,取决于全文索引配置的分析器。例如,瑞典语分析器可以对瑞典语文本进行分词和提取主干(stem),避免索引中包含瑞典语的停用词。
	● 支持对节点和关系的索引。
	● 支持自定义分析器,可以不使用Lucene自带的分析器。
	● 可以使用Lucene语言进行查询。
	● 可以给查询的每个结果打分。
	● 节点和关系增删改后索引自动更新。
	● 使用当前数据自动填充新创建的索引。
	● 可以用一致性检查器进行检查,检查存在问题时可以重建索引。
	● 只能通过属性的值来索引节点和关系。
	● 可以在单个索引中支持任意数量的文档。
	● 创建、删除和更新都是事务性操作,并在集群中自动复制。
	● 可以通过Cypher程序访问。
	● 可以配置为最终一致性模式。该模式下索引的更新操作由后台线程执行。这一功能可以解决提交过程中Lucene写入慢的问题,从而消除Neo4j写入性能的主要瓶颈。
与b树索引相比,全文索引有以下优势:
	● 支持多个标签。
	● 支持多个关系类型。
	● 支持多个属性。这一点类似于复合索引,但有一个重要区别:复合索引的对象必须具有被索引标签和全部被索引属性,但全文索引的对象只要具有至少一个被索引标签或关系类型,和至少一个被索引属性即可。
17.7.1、创建全文索引
	通过命令create fulltext index创建全文索引。
	创建节点的全文索引:
		create fulltext index [index_name] [if not exists] for (n:LabelName [, ...]) on each [n.propertyName [, ...] ] options {option: value [, ...] }
	创建关系的全文索引:
		create fulltext index [index_name] [if not exists] for ()-[r:TYPE [, ...]]-() on each [r.propertyName [, ...] ] options {option: value [, ...] }
	其中,OPTION子句支持以下配置项:
		● indexProvider:默认值只能是fulltext-1.0。
		● indexConfig:可以使用以下参数:
			➢ 参数fulltext.analyzer:用于指定分析器。使用db.index.fulltext.listAvailableAnalyzers过程查看可用的选项。
			➢ 参数fulltext.eventually_consistent:最终一致性标志。设置为true时,提交的更新事务将在后台线程中处理,而不是前台提交,可以使该索引满足最终一致性。
17.7.2、基于全文索引的查询
	通过过程db.index.fulltext.queryNodes和db.index.fulltext.queryRelationships可以实现基于全文索引的查询。其返回结果中既包含精确匹配的结果,也包含近似匹配的结果。被索引的属性值和基于索引的查询都经过分析器处理,以便索引可以找到近似匹配的结果。每一条查询结果都包含一个分数(score),代表了该结果的匹配程度。所有查询结果按分数降序排列,最匹配的结果放在第一条。
	 	例:call db.index.fulltext.queryNodes("titlesAndDescriptions", "Full Metal Jacket") yield node,  score
	全文索引由Apache Lucene索引和搜索库提供支持,所以可以使用Lucene的全文查询语言。例如,如果只想得到精确匹配结果,那么将目标字符串加英文单引号。
		例:call db.index.fulltext.queryNodes("titlesAndDescriptions", '"Full Metal Jacket"') yield node,  score
	Lucene语法中还允许使用逻辑运算符(比如AND和OR)来搜索。
		例:call db.index.fulltext.queryNodes("titlesAndDescriptions", 'full AND metal') yield node,  score
	还可以只搜索特定的属性:在要搜索的文本前面加上属性名称和冒号。
		例:call db.index.fulltext.queryNodes("titlesAndDescriptions", 'description:"surreal adventure"') yield node,  score
17.7.3、删除全文索引
	drop index taggedByRelationshipIndex
18、约束
18.1、约束类型
Neo4j通过使用约束来保证数据完整性,可应用于节点或者关系。约束的类型包括:
1、节点属性的唯一性约束。确保具有特定标签的所有节点的某个属性唯一。针对多个属性建立的唯一性约束,则确保这些属性值的组合是唯一的。唯一性约束并不要求所有节点对于相关属性都具有唯一值,如果节点不包含约束相关的全部属性,则该节点不受此约束限制。
2、节点属性的存在性约束(仅企业版)。确保具有特定标签的所有节点都具有某个属性。如果创建具有这种标签的节点时没有设定该属性,则创建失败。删除节点的这类属性同样也会失败。
3、关系属性的存在性约束(仅企业版)。确保具有特定类型的所有关系都存在属性。如果创建具有这些类型的关系时没有设定该属性,则创建失败。删除关系的这类属性同样也会失败。
4、节点键约束(仅企业版)。确保给定标签下的所有节点都拥有所有约束相关的属性,且属性的值唯一。如果创建了该类约束,则以下操作都不能执行:
	● 创建未包含全部属性的节点或属性值不唯一的节点。
	● 删除约束相关属性。
	● 导致属性值不再唯一的更新。
18.2、约束影响
1、为属性创建节点键约束或节点属性唯一性约束,会自动在该属性上创建一个索引,因此约束一旦创建,就不能另外单独创建相同索引类型、标签和属性组合的索引。
2、这些自动创建的索引也可以被Cypher使用。
3、如果约束被删除,相关索引也被删除,如果仍需使用约束所自动创建的索引,则需要手动重新创建这些索引。
18.3、约束特定
1、一个标签可以有多个约束,属性的唯一性约束和存在性约束可以绑定在同一个属性上。
2、创建约束是原子操作,且因为需要扫描全库,所以可能会花费较长的时间。
3、最好在创建约束时就为其命名,否则系统会自动生成一个名称。
4、约束名称必须在索引和约束中都唯一。
5、默认情况下,创建约束的操作不可重复执行。两次创建相同的约束会引发报错,可以使用关键字IF NOT EXISTS防止这种情况。
18.4、创建约束
1、创建节点唯一性约束:
	create constraint [ constraint_name ] [ if not exists] for ( n:LabelName) require ( n.propertyName1, ..., n.propertyName) is unique options { option: value [, ...] }
2、创建节点属性的存在性约束(仅企业版支持该操作):
	create constraint [ constraint_name ] [ if not exists] for ( n:LabelName) require n.propertyName is not null 
3、创建关系属性的存在性约束(仅企业版支持该操作):
	create constraint [ constraint_name ] [ if not exists] for ()-[r:RelationshipType]-() require r.propertyName is not null
4、创建节点键约束(仅企业版支持该操作):
	create constraint [ constraint_name ] [ if not exists] for ( n:LabelName) require ( n.propertyName1, ..., n.propertyName) is node key options { option: value [, ...] }
OPTIONS子句可以指定约束自动创建索引时采用的索引程序和索引配置项,与索引的OPTIONS子句配置类似。
IF NOT EXISTS子句可以避免重复创建相同的约束时引发的报错,但如果存在冲突的数据、索引或约束,仍可能会报错,比如节点缺少属性、已存在同名索引,或约束的schema相同但类型不同。
18.5、删除约束
drop constraint constraint_name if exists
18.6、列出约束
show [ all | unique | node[property] exist[ence] | rel[ationship]   | node key] constraint[s] [ where expression]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值