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:没有匹配到情况下,默认返回表达式。
参数能够用于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
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
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
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]