CQL简介
CQL代表Cypher查询语言。 像关系型数据库具有查询语言SQL,Neo4j使用CQL作为查询语言。常用的Neo4j CQL命令/条款如下:
CQL命令/条 | 作用 |
CREATE 创建 | 创建节点,关系和属性 |
MATCH 匹配 | 检索有关节点,关系和属性数据 |
RETURN 返回 | 返回查询结果 |
WHERE 条件 | 提供条件过滤检索MATCH数据 |
DELETE 删除 | 删除节点和关系 |
REMOVE 移除 | 删除节点和关系的属性 |
SET 设置 | 添加或更新标签 |
ORDER BY 排序 | 对结果排序 |
SKIP LIMIT 分页 | 分页 |
DISTINCT 排重 | 排重 |
官网文档地址:https://neo4j.com/docs/cypher-manual/4.3/introduction/。
为了完成上面的语法,我们基于庆余年电视剧人物关系图片来创建我们的测试数据:
// 删除所有的节点和关系
MATCH(n) OPTIONAL MATCH (n)-[r]-() DELETE n,r
// 创建Person 的节点
CREATE (person:Person {cid:1,name:"范闲",age:24,gender:0,character:"A",money:1000,description:"范闲,是猫腻小说《庆余年》主人公,穿越人士,庆国数十年风雨画卷的见证者。其容貌俊美无双,尤胜于女子,生性淡薄刚毅,善良而腹黑,城府极深,重视恩情。最终隐居江南"});
CREATE (person:Person {cid:2,name:"林婉儿",age:20,gender:1,character:"B",money:800,description:"林婉儿是庆国宰相和长公主的私生女,电视剧《庆余年》里的女主人公,由李沁饰演"});
CREATE (person:Person {cid:3,name:"庆帝",age:49,gender:0,character:"A",money:8900,description:"庆帝,网文作家猫腻所著的权谋小说《庆余年》的角色之一,南庆国的皇帝,心中装有天下统一"});
CREATE (person:Person {cid:4,name:"长公主",age:46,gender:1,character:"B",money:3700,description:"《庆余年》中,长公主这个人不仅人设很复杂,就连她的感情生活还是挺复杂。长公主所处的身份就是庆国的公主,皇帝的妹妹,太子的姑姑,国家重要财权的掌管,林婉儿的母亲"});
CREATE (person:Person {cid:5,name:"宰相林若甫",age:47,gender:0,character:"A",money:1600,description:"林若甫,是电视剧《庆余年》登场的虚拟人物之一,南庆当朝宰相,林婉儿的亲生父亲。"});
CREATE (person:Person {cid:6,name:"叶灵儿",age:20,gender:1,character:"C",money:700,description:"叶灵儿,网文作家猫腻所著的权谋小说《庆余年》的角色之一,林婉儿的好友,最后嫁给了二皇子"});
CREATE (person:Person {cid:7,name:"九品射手燕小乙",age:47,gender:0,character:"C",money:900,description:"一品最低,九品最高。庆帝身边的燕小乙便是九品,而且是庆国独一无二的神射手,臂力、眼力、听力惊人"});
CREATE (person:Person {cid:8,name:"二皇子",age:26,gender:0,character:"B",money:1700,description:"《庆余年》中,二皇子结局自杀身亡。二皇子对庆帝也是意见很大,但以他的实力还掀不起什么水花,所以只能慢慢等待时机"});
CREATE (person:Person {cid:9,name:"靖王世子",age:25,gender:0,character:"A",money:1600,description:"在《庆余年》中,此靖王非彼靖王,但是同音之美也会让人会对靖王世子李弘成这个角色产生好感,而靖王世子李弘成的出场的确是帮助了范闲逃脱太子势力的纠缠"});
CREATE (person:Person {cid:10,name:"王启年",age:46,gender:0,character:"C",money:1700,description:"王启年,网文作家猫腻所著的权谋小说《庆余年》的角色之一,庆国监察院一处的文书,擅长追踪之术。"});
CREATE (person:Person {cid:11,name:"北齐圣女海棠朵朵",age:21,gender:1,character:"A",money:2600,description:"海棠朵朵是北齐国的才女,被人尊称为圣女,而且是北齐大宗师苦荷的关门弟子,在北齐国也算是举足轻重的人物"});
CREATE (person:Person {cid:12,name:"北齐小皇帝战豆豆",age:20,gender:0,character:"A",money:4600,description:"很多人想知道剧中的北齐小皇帝是谁呢?让小编告诉你们吧。 战豆豆是北齐第二任皇帝,乃前北魏一代大将战清风之孙,大宗师苦荷的叔侄女兼徒孙"});
//创建关系
match(person:Person {name:"范闲"}),(person2:Person {name:"林婉儿"}) create(person)-[r:Couple]->(person2);
match(person:Person {name:"范闲"}),(person2:Person {name:"王启年"}) create(person)-[r:Friends]->(person2);
match(person:Person {name:"范闲"}),(person2:Person {name:"北齐圣女海棠朵朵"}) create(person)-[r:Friends]->(person2);
match(person:Person {name:"范闲"}),(person2:Person {name:"庆帝"}) create(person)-[r:Father]->(person2);
match(person:Person {name:"范闲"}),(person2:Person {name:"长公主"}) create(person)-[r:Wife_Mother]->(person2);
match(person:Person {name:"庆帝"}),(person2:Person {name:"二皇子"}) create(person)-[r:Son]->(person2);
match(person:Person {name:"庆帝"}),(person2:Person {name:"长公主"}) create(person)-[r:BrotherSister]->(person2);
match(person:Person {name:"二皇子"}),(person2:Person {name:"靖王世子"}) create(person)-[r:Friends]->(person2);
match(person:Person {name:"北齐圣女海棠朵朵"}),(person2:Person {name:"北齐小皇帝战豆豆"}) create(person)-[r:Friends]->(person2);
match(person:Person {name:"林婉儿"}),(person2:Person {name:"叶灵儿"}) create(person)-[r:Friends]->(person2);
match(person:Person {name:"林婉儿"}),(person2:Person {name:"宰相林若甫"}) create(person)-[r:Father]->(person2);
match(person:Person {name:"林婉儿"}),(person2:Person {name:"长公主"}) create(person)-[r:Mother]->(person2);
match(person:Person {name:"长公主"}),(person2:Person {name:"九品射手燕小乙"}) create(person)-[r:Friends]->(person2);
CREATE
CREATE (
<node-name>:<label-name>
[{
<property1-name>:<property1-Value>
........
<propertyn-name>:<propertyn-Value>
}]
)
语法说明:
语法元素 | 描述 |
<node-name> | 它是我们将要创建的节点名称 |
<label-name> | 它是一个节点标签名称 |
<property1-name>…< propertyn-name> | 属性是键值对。 定义将分配给创建节点的属性的名称 |
<property1-value>…< propertyn-value> | 属性是键值对。 定义将分配给创建节点的属性的值 |
举例:
CREATE (person:Person)
CREATE (person:Person {cid:1,name:"范
闲",age:24,gender:0,character:"A",money:1000});
CREATE (person:Person {cid:2,name:"林婉
儿",age:20,gender:1,character:"B",money:800});
CREATE (person:Person {cid:3,name:"庆
帝",age:49,gender:0,character:"A",money:8900});
注意:这里的node-name可以理解为临时变量,它会保存在数据库里面但是不用于查询,所以节点的node-name相同不影响数据节点的创建。label-name可以理解为分类名称,这个名称很重要,之后的查询主要是用label-name来查询。
MATCH RETURN命令语法
MATCH
(
<node-name>:<label-name>
)
RETURN
<node-name>.<property1-name>,
...
<node-name>.<propertyn-name>
语法元素 | 描述 |
<node-name> | 它是我们将要创建的节点名称 |
<label-name> | 它是一个节点标签名称 |
<property1-name>…< propertyn-name> | 属性是键值对。 定义将分配给创建节点的属性的名称 |
举例:
MATCH (person:Person) return person
MATCH (person:Person) return person.name,person.age
关系创建
- 使用现有节点创建没有属性的关系
MATCH (<node1-name>:<node1-label-name>{property1-name:property1-value,...}),(<node2-name>:<node2-label-name>{property1-name:property1-value,...})
CREATE
(<node1-name>)-[<relationship-name>:<relationship-label-name>]->(<node2-
name>)
RETURN 相应的内容
语法说明:
语法元素 | 描述 |
MATCH,CREATE,RETURN | 他们是Neo4J CQL关键字 |
<noode1-name> | 它用于创建关系的“From Node”的名称 |
<node1-label-name> | 它用于创建关系的“From Node”的标签名称 |
<node2-name> | 它用于创建关系的“To Node”的名称 |
<node2-label-name> | 它用于创建关系的“To Node”的标签名称 |
<property1-name>…< propertyn-name> | 键值对名称。用于匹配查询出对应节点 |
<property1-value>…< propertyn-value> | 键值对值。用于匹配查询出对应节点 |
<relationship-name> | 这是一个关系的名称 |
<relationship-label-name> | 它是一个关系的标签名称 |
示例:
创建关系
match(person:Person {name:"范闲"}) ,(person2:Person {name:"林婉儿"})
create(person)-[r:Couple]->(person2);
查询关系
match p = (person:Person {name:"范闲"})-[r:Couple]->(person2:Person) return p
match (p1:Person {name:"范闲"})-[r:Couple]-(p2:Person) return p1,p2
match (p1:Person {name:"范闲"})-[r:Couple]-(p2:Person) return r
- 使用现有节点创建有属性的关系
MATCH (<node1-label-name>:<node1-name>),(<node2-label-name>:<node2-name>)
CREATE
(<node1-label-name>)-[<relationship-label-name>:<relationship-name>
{<define-properties-list>}]->(<node2-label-name>)
RETURN <relationship-label-name>
其中<define-properties-list> 是分配给新创建关系的属性(名称 - 值对)的列表。
{
<property1-name>:<property1-value>,
<property2-name>:<property2-value>,
...
<propertyn-name>:<propertyn-value>
}
示例:
MATCH (person:Person {name:"范闲"}),(person2:Person {name:"林婉儿"})
CREATE (person)-[r:Couple{mary_date:"12/12/2014",price:55000}]->(person2)
RETURN r
- 使用新节点创建没有属性的关系
CREATE
(<node1-name>:<node1-label-name>)
-[<relationship-name>:<relationship-label-name>]->
(<node1-name>:<node1-label-name>)
示例如下:
CREATE (person1:Person {cid:4,name:"长公
主",age:49,gender:1,character:"A",money:5000})
-[r:Friend]->
(person2:Person {cid:7,name:"九品射手燕小
乙",age:48,gender:0,character:"B",money:1000})
- 使用新节点创建有属性的关系
CREATE (<node1-name>:<node1-label-name>) -[<relationship-name>:<relationship-label-name>{<define-properties-list>}]-> (<node1-name>:<node1-label-name>)
示例:
CREATE (person1:Person {cid:9,name:"靖王世
子",age:23,gender:0,character:"A",money:3000})
-[r:Friend {date:"11-02-2000"}]->
(person2:Person {cid:8,name:"二皇子",age:24,gender:0,character:"B",money:6000})
关系和节点的属性可以使用的类型:
CQL数据类型 | 作用 |
boolean | 它用于表示布尔文字:true, false |
byte | 它用来表示8位整数 |
short | 它用于表示16位整数 |
int | 它用于表示32位整数 |
long | 它用于表示64位整数 |
float | 浮点数用于表示32位浮点数 |
double | Double用于表示64位浮点数 |
char | Char用于表示16位字符 |
String | 字符串用于表示字符串 |
CREATE创建多个标签
CREATE (<node-name>:<label-name1>:<label-name2>.....:<label-namen>)
如:
CREATE (person:Person:Beauty:Picture {cid:20,name:"小美女"})
WHERE子句
简单的WHERE子句
WHERE <condition>
复杂的WHERE子句
WHERE <condition> <boolean-operator> <condition>
WHERE中的比较运算符和之前MySQL的相同。如 = 、!=、 >、< 等。
布尔运算符 | 描述 |
AND | 与 |
OR | 或 |
NOT | 非 |
示例:
MATCH (person:Person)
WHERE person.name = '范闲' OR person.name = '靖王世子'
RETURN person
DELETE子句和REMOVE子句
DELETE子句
- 删除节点
- 删除节点及相关节点和关系
MATCH p = (:Person {name:"林婉儿"})-[r:Couple]-(:Person)
DELETE r
REMOVE子句
- 删除节点或关系的标签
- 删除节点或关系的属性
MATCH (person:Person {name:"小美女"})
REMOVE person.cid
SET子句
- 向现有节点或关系添加新属性
- 更新属性值
MATCH (person:Person {cid:1})
SET person.money = 3456,person.age=25
ORDER BY子句
ORDER BY
子句,对MATCH
查询返回的结果进行排序。我们可以按升序或降序对行进行排序。默认情况下,它按升序对行进行排序。 如果我们要按降序对它们进行排序,我们需要使用DESC
子句。
MATCH (person:Person)
RETURN person.name,person.money
ORDER BY person.money DESC
SKIP和LIMIT
Neo4j CQL已提供SKIP
子句来过滤或限制查询返回的行数。 它修整了CQL查询结果集顶部的结果。
Neo4j CQL已提供LIMIT
子句来过滤或限制查询返回的行数。 它修剪CQL查询结果集底部的结果。
MATCH (person:Person)
RETURN ID(person),person.name,person.money
ORDER BY person.money DESC
SKIP 4 LIMIT 2
DISTINCT排重
这个函数的用法就像SQL中的DISTINCT
关键字,返回的是所有不同值。
MATCH (p:Person)
RETURN DISTINCT(p.character)
CQL函数
字符串函数
功能 | 描述 |
UPPER | 它用于将所有字母更改为大写字母 |
LOWER | 它用于将所有字母改为小写字母 |
SUBSTRING | 它用于获取给定String的子字符串 |
REPLACE | 它用于替换一个字符串的子字符串 |
MATCH (p:Person)
RETURN ID(p),LOWER(p.character)
MATCH(p:Person)
RETURN
p.character,LOWER(p.character),p.name,SUBSTRING(p.name,2),REPLACE(p.name,"子","z
i")
聚合函数
聚集功能 | 描述 |
COUNT | 它返回由MATCH命令返回的行数 |
MAX | 它从MATCH命令返回的一组行返回最大值 |
MIN | 它返回由MATCH命令返回的一组行的最小值 |
SUM | 它返回由MATCH命令返回的所有行的求和值 |
AVG | 它返回由MATCH命令返回的所有行的平均值 |
MATCH (p:Person)
RETURN MAX(p.money),SUM(p.money)
关系函数
功能 | 描述 |
STARTNODE | 它用于知道关系的开始节点 |
ENDNODE | 它用于知道关系的结束节点 |
ID | 它用于知道关系的ID |
TYPE | 它用于知道字符串表示中的一个关系的TYPE |
MATCH p = (:Person {name:"林婉儿"})-[r:Couple]-(:Person)
RETURN STARTNODE(r)
shortestPath
函数
该函数用于返回最短的path。示例如下:
MATCH p=shortestPath( (node1)-[*]-(node2) )
RETURN length(p), nodes(p)
MATCH p=shortestPath((person:Person {name:"王启年"})-[*]-(person2:Person
{name:"九品射手燕小乙"}) )
RETURN length(p), nodes(p)
CQL多深度关系节点
使用with
关键字
查询三层级关系节点如下:with
可以将前面查询结果作为后面查询条件
MATCH (na:Person)-[re]->(nb:Person)
WHERE na.name="范闲"
WITH na,re,nb
MATCH (nb:Person)-
[re2]->(nc:Person)
RETURN na,re,nb,re2,nc
MATCH (na:Person)-[re]->(nb:Person)
WHERE na.name="林婉儿"
WITH na,re,nb
MATCH (nb:Person)-
[re2]->(nc:Person)
RETURN na,re,nb,re2,nc
MATCH (na:Person)-[re]-(nb:Person)
WHERE na.name="林婉儿"
WITH na,re,nb
MATCH (nb:Person)-
[re2]->(nc:Person)
RETURN na,re,nb,re2,nc
MATCH (na:Person)-[re]-(nb:Person)
WHERE na.name="林婉儿"
WITH na,re,nb
MATCH (nb:Person)-
[re2:Friends]->(nc:Person)
RETURN na,re,nb,re2,nc
直接拼接关系节点查询
MATCH (na:Person{name:"范闲"})-[re]->(nb:Person)-[re2]->(nc:Person)
RETURN na,re,nb,re2,nc
为了方便,可以将查询结果赋给变量,然后返回
MATCH data=(na:Person{name:"范闲"})-[re]->(nb:Person)-[re2]->(nc:Person)
RETURN data
使用深度运算符
当实现多深度关系节点查询时,显然使用以上方式比较繁琐。
深度查询表达式如下:
节点1-[:TYPE*minHops..maxHops]->节点2
示例:
MATCH (charlie {name: 'Charlie Sheen'})-[:ACTED_IN*1..3]-(movie:Movie)
RETURN movie.title
上述示例指的是查询 charlie 节点到movie节点1到3层关系,且关系标签为ACTED_IN的电影名称。
详细可以参考官方文档:https://neo4j.com/docs/cypher-manual/4.3/clauses/match/#rel-types-with-uncommon-chars。
事务
为了保持数据的完整性和保证良好的事务行为,Neo4j也支持ACID特性 。
注意:
- 所有对Neo4j数据库的数据修改操作都必须封装在事务里
- 默认的
isolation level
是READ_COMMITTED
- 死锁保护已经内置到核心事务管理 。 (Neo4j会在死锁发生之前检测死锁并抛出异常。在异常抛出之前,事务会被标志为回滚。当事务结束时,事务会释放它所持有的锁,则该事务的锁所引起的死锁也就是解除,其他事务就可以继续执行。当用户需要时,抛出异常的事务可以尝试重新执行
- 除特别说明,Neo4j的API的操作都是线程安全的,Neo4j数据库的操作也就没有必要使用外部的同步方法
索引
简介
Neo4j CQL支持节点或关系属性上的索引,以提高应用程序的性能。可以为具有相同标签名称的属性上创建索引。可以在MATCH
或WHERE
等运算符上使用这些索引列来改进CQL 的执行。
创建单一索引
CREATE INDEX ON :Label(property)
例如:
CREATE INDEX ON :Person(name)
创建复合索引
CREATE INDEX ON :Person(age, gender)
全文模式索引
之前的常规模式索引只能对字符串进行精确匹配或者前后缀索引(startswith,endswith,contains),全文索引将标记化索引字符串值,因此它可以匹配字符串中任何位置的术语。索引字符串如何被标记化并分解为术语,取决于配置全文模式索引的分析器。索引是通过属性来创建,便于快速查找节点或者关系。
创建全文模式索引:
call db.index.fulltext.createNodeIndex("索引名",[Label,Label],[属性,属性])
call db.index.fulltext.createNodeIndex("nameAndDescription",["Person"],["name",
"description"])
call db.index.fulltext.queryNodes("nameAndDescription", "范闲") YIELD node, score
RETURN node.name, node.description, score
查看和删除索引
查看索引
call db.indexes
或者
:schema
删除索引
DROP INDEX ON :Person(name)
DROP INDEX ON :Person(age, gender)
call db.index.fulltext.drop("nameAndDescription")
约束
唯一性约束
CREATE CONSTRAINT ON (变量:<label_name>) ASSERT 变量.<property_name> IS UNIQUE
具体实例:
CREATE CONSTRAINT ON (person:Person) ASSERT person.name IS UNIQUE
删除唯一性约束:
DROP CONSTRAINT ON (cc:Person) ASSERT cc.name IS UNIQUE
属性存在约束 (企业版中可用)
CREATE CONSTRAINT ON (p:Person) ASSERT exists(p.name)
查看约束
call db.constraints
或者
:schema
以上就是本文的全部内容。欢迎各位小伙伴积极留言交流~~~
文章评论