neo4j简介
Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中。它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储在网络(从数学角度叫做图)上而不是表中
节点:图形数据记录 关系:连接节点 标签:用于修饰节点,例如:人、工具等,一个节点可以有0个或者多个 属性:命名数据值,例如:人的姓名,年龄,可以修饰节点和关系
介绍
数据库语句使用Cypher编写 任何查询结果的可导出表格结果 包含节点和关系的查询结果的图形可视化 方便地探索Neo4j的REST API
优点
数据的插入,查询操作很直观,不用再像之前要考虑各个表之间的关系。 提供的图搜索和图遍历方法很方便,高性能。 用图论的方法查找用户之间的关系网是很方便的,查询速度也极快,它可以查出通过朋友可能认识的人(二度人脉),甚至三度人脉及多度人脉,还可以查出两个用户间最短路径。 支持事物
缺点
不能进行分布式存储,想要提高性能和容量只能加大机器的硬盘、使用更高的内存和SSD,硬件最终会达到瓶颈 社区不够活跃,遇到问题需要自己爬坑 …
使用
docker run -it -d -p 7474:7474 -p 7687:7687 neo4j:latest 默认密码是neo4j 本地访问http://localhost:7474/browser/,可以更改密码
Cypher命令
CQL命令/条 用法 CREATE 创建 创建节点,关系和属性 MATCH 匹配 检索有关节点,关系和属性数据 RETURN 返回 返回查询结果 WHERE 哪里 提供条件过滤检索数据 DELETE 删除 删除节点和关系 REMOVE 移除 删除节点和关系的属性 ORDER BY以…排序 排序检索数据 SET 组 添加或更新标签
CREATE (
<node-name>:<label-name1>:<label-name2>....<label-namen>
{
<key>:<Value>,
........
<n-key>:<n-Value>
}
)
MATCH (<node-name>:<label-name1>) return <node-name>.<property1-name>,<node-name>.<property2-name>
比较运算符 作用 = 它是Neo4j CQL“等于”运算符。 <> 它是一个Neo4j CQL“不等于”运算符。 < 它是一个Neo4j CQL“小于”运算符。 > 它是一个Neo4j CQL“大于”运算符。 <= 它是一个Neo4j CQL“小于或等于”运算符。 = 它是一个Neo4j CQL“大于或等于”运算符。
关系运算符 作用 AND 它是一个支持AND操作的Neo4j CQL关键字。 OR 它是一个Neo4j CQL关键字来支持OR操作。 NOT 它是一个Neo4j CQL关键字支持NOT操作。 XOR 它是一个支持XOR操作的Neo4j CQL关键字。
WHERE <property-name> <comparison-operator> <value>
// 箭头可以是双向的
-[r:DemoRelation]->
// 使用已有的节点创建关系
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>
DELETE <node-name-list>
MATCH (cc: CreditCard)-[rel]-(c:Customer)
DELETE cc,c,rel
remove 删除节点或关系的标签 删除节点或关系的属性
MATCH (m:Movie)
REMOVE m:Pic
SET <node-label-name>.<property1-name>,...<node-laben-name>.<propertyn-name>
MATCH (cc:CreditCard) RETURN cc.id,cc.number
UNION
MATCH (dc:DebitCard) RETURN dc.id,dc.number
// 显示前两行
MATCH (emp:Employee)
RETURN emp
LIMIT 2
// 显示后两行
MATCH (emp:Employee)
RETURN emp
SKIP 2
MERGE命令在图中搜索给定模式,如果存在,则返回结果;如果它不存在于图中,则它创建新的节点/关系并返回结果。 MERGE = CREATE + MATCH
MERGE (<node-name>:<label-name>
{
<key>:<1-Value>
.....
<n-key>:<n-Value>
})
MATCH (e:Employee)
WHERE e.id IS NOT NULL
RETURN e.id,e.name,e.sal,e.deptno
MATCH (e:Employee)
WHERE e.id IN [123,124]
RETURN e.id,e.name,e.sal,e.deptno
CREATE INDEX ON :<label_name> (<property_name>)
DROP INDEX ON :<label_name> (<property_name>)
CREATE CONSTRAINT ON (<label_name>)
ASSERT <property_name> IS UNIQUE
DISTINCT独特 这个函数的用法就像SQL中的distinct关键字,返回的是所有不同值。
MATCH (n:Movie) RETURN Distinct(n.name)
Cypher函数
定制列表功能 用法 String 字符串 它们用于使用String字面量。 Aggregation 聚合 它们用于对CQL查询结果执行一些聚合操作。 Relationship 关系 他们用于获取关系的细节,如startnode,endnode等。
定制列表功能 用法 语法 UPPER 它用于将所有字母更改为大写字母。 UPPER () LOWER 它用于将所有字母改为小写字母。 LOWER () SUBSTRING 它用于获取给定String的子字符串。 SUBSTRING(, ,) REPLACE 它用于替换一个字符串的子字符串。
AGGREGATION聚合: 和SQL一样,Neo4j CQL提供了一些在RETURN子句中使用的聚合函数。 它类似于SQL中的GROUP BY子句。
聚集功能 描述 用法 COUNT 它返回由MATCH命令返回的行数。 MATCH (e:Employee) RETURN COUNT(*) MAX 它从MATCH命令返回的一组行返回最大值。 MAX( ) MIN 它返回由MATCH命令返回的一组行的最小值。 MIN( ) SUM 它返回由MATCH命令返回的所有行的求和值。 SUM( ) AVG 它返回由MATCH命令返回的所有行的平均值。 AVG( )
功能 描述 STARTNODE 它用于知道关系的开始节点。 ENDNODE 它用于知道关系的结束节点。 ID 它用于知道关系的ID。 TYPE 它用于知道字符串表示中的一个关系的TYPE。
MATCH (a)-[movie:ACTION_MOVIES]->(b)
RETURN STARTNODE(movie)
ENDNODE
MATCH (a)-[movie:ACTION_MOVIES]->(b)
RETURN ENDNODE(movie)
ID TYPE
MATCH (a)-[movie:ACTION_MOVIES]->(b)
RETURN ID(movie),TYPE(movie)
neo4j数据格式
CQL数据类型 用法 boolean 用于表示布尔文字:true,false。 byte 用于表示8位整数。 short 用于表示16位整数。 int 用于表示32位整数。 long 用于表示64位整数。 float I用于表示32位浮点数。 double 用于表示64位浮点数。 char 用于表示16位字符。 String 用于表示字符串。
java灵魂代码
消除DAO层中的boiler plate代码 DAO层中的工件少 易于开发和维护 改进开发过程
支持基于XML的实体映射 支持基于注释的实体映射 支持分页 支持事务 更少的DAO层工件 - 实现存储库
< dependency>
< groupId> org. neo4j< / groupId>
< artifactId> neo4j- ogm- http- driver< / artifactId>
< / dependency>
< dependency>
< groupId> org. springframework. boot< / groupId>
< artifactId> spring- boot- starter- data- neo4j< / artifactId>
< / dependency>
@NodeEntity ( label = "Bot" )
public class BotNode {
@Id
@GeneratedValue
private Long id;
@Property ( name = "name" )
private String name;
@Property ( name = "kind" )
private String kind;
@Property ( name = "weight" )
private long weight;
public BotNode ( ) {
}
public BotNode ( Long id, String name, String kind, long weight) {
this . id = id;
this . name = name;
this . kind = kind;
this . weight = weight;
}
public Long getId ( ) {
return id;
}
public void setId ( Long id) {
this . id = id;
}
public String getName ( ) {
return name;
}
public void setName ( String name) {
this . name = name;
}
public String getKind ( ) {
return kind;
}
public void setKind ( String kind) {
this . kind = kind;
}
public long getWeight ( ) {
return weight;
}
public void setWeight ( long weight) {
this . weight = weight;
}
@Override
public String toString ( ) {
return "BotNode{" +
"id=" + id +
", name='" + name + '\'' +
", kind='" + kind + '\'' +
", weight=" + weight +
'}' ;
}
}
@RelationshipEntity ( type = "BotRelation" )
public class BotRelation {
@Id
@GeneratedValue
private Long id;
@StartNode
private BotNode startNode;
@EndNode
private BotNode endNode;
@Property
private String relation;
public BotRelation ( ) {
}
public BotRelation ( Long id, BotNode startNode, BotNode endNode, String relation) {
this . id = id;
this . startNode = startNode;
this . endNode = endNode;
this . relation = relation;
}
public String getRelation ( ) {
return relation;
}
public void setRelation ( String relation) {
this . relation = relation;
}
public Long getId ( ) {
return id;
}
public void setId ( Long id) {
this . id = id;
}
public BotNode getStartNode ( ) {
return startNode;
}
public void setStartNode ( BotNode startNode) {
this . startNode = startNode;
}
public BotNode getEndNode ( ) {
return endNode;
}
public void setEndNode ( BotNode endNode) {
this . endNode = endNode;
}
@Override
public String toString ( ) {
return "BotRelation{" +
"id=" + id +
", startNode=" + startNode +
", endNode=" + endNode +
", relation='" + relation + '\'' +
'}' ;
}
}
@Repository
public interface BotRepository extends Neo4jRepository < BotNode, Long> {
BotNode findAllByName ( String name) ;
@Query ( "MATCH p=(n:Bot)-[r:BotRelation]->(m:Bot) WHERE id(n)={0} RETURN p" )
List< BotRelation> findAllByBotNode ( BotNode botNode) ;
@Query ( "MATCH p=(n:Bot)<-[r:BotRelation]->(m:Bot) WHERE m.name={name} RETURN p" )
List< BotRelation> findAllBySymptom ( @Param ( "name" ) String name) ;
@Query ( "MATCH p=(n:Bot)<-[r:BotRelation]->(m:Bot)<-[:BotRelation]->(:Bot)<-[:BotRelation]->(n:Bot) WHERE n.name={name} RETURN p" )
List< BotRelation> findAllByStartNode ( @Param ( "name" ) String name) ;
}
@RunWith ( SpringRunner. class )
@SpringBootTest
public class Neo4jApplicationTests {
@Autowired
MovieRepository movieRepository;
@Test
public void contextLoads ( ) {
movieRepository. save ( new Movie ( "《奥特曼》" ) ) ;
System. out. println ( movieRepository. findAll ( ) ) ;
}
}
资料
Cypher实例
// 创建节点
create(suxun:Person_{name:"苏洵",age:80,sex:"男"})
create(sushi:Person_{name:"苏轼",age:53,sex:"男"})
create(suzhe:Person_{name:"苏辙",age:51,sex:"男"})
create(suxiaomei:Person_{name:"苏小妹",age:45,sex:"女"})
create(susun:Person_{name:"苏孙",age:29,sex:"男"})
create(suxiaosun:Person_{name:"苏重孙",age:6,sex:"女"})
// 创建关系
match(p1:Person_),(p2:Person_)
where p1.name="苏洵" and p2.name = "苏轼"
create (p1) -[parent:Parent{relation:"父亲"}]-> (p2);
match(p1:Person_),(p2:Person_)
where p1.name="苏洵" and p2.name = "苏辙"
create (p1) -[parent:Parent{relation:"父亲"}] -> (p2);
match(p1:Person_),(p2:Person_)
where p1.name="苏洵" and p2.name = "苏小妹"
create (p1) -[parent:Parent{relation:"父亲"}] -> (p2);
match(p1:Person_),(p2:Person_)
where p1.name="苏轼" and p2.name = "苏孙"
create (p1) -[parent:Parent{relation:"父亲"}] -> (p2);
match(p1:Person_{name:"苏孙"}),(p2:Person_{name:"苏重孙"})
create (p1) -[parent:Parent{relation:"父亲"}] -> (p2);
// 查询所有的关系节点
match(a)-[r:Parent]->(b) return a, r, b
// 筛选出子孙绵延四代的树干
match(a)-[r1:Parent]->(b)-[r2:Parent]->(c)-[r3:Parent]->(d) return a, b, c, d
// 筛选出存在三代子孙的树干
match(a)-[r1:Parent]->(b)-[r2:Parent]->(c) return a, b, c
// 筛选出某个节点为顶点的三代子孙树干
match(a{name:"苏洵"})-[r1:Parent]->(b)-[r2:Parent]->(c) return a, b, c
// 删除苏轼有关的节点和关系
match (b)-[r1]-(a{name: "苏轼"})-[r2]->(c) delete r1, a, r2 return r1, a, r2
// 创苏轼并创建关系
match (a:Person_), (b:Person_), (c:Person_) where a.name = "苏洵" and b.name = "苏孙" and c.name="苏轼"
create (a)-[r:Parent]->(c)-[r1:Parent]->(b)
// 添加属性
match (a:Person_) where a.name = "苏轼" set a.a="a"
// 删除属性
match (a:Person_) where a.name = "苏轼" remove a.a
// 条件查询
match (a:Person_) where a.name in ["苏轼", "苏辙"] return a
// 函数
match (a:Person_) where a.name in ["苏轼", "苏辙"] return count(a)
// 比较运算符
match (a:Person_) where a.name <> "苏轼" return a
// 删除全部节点和关系
match (node)-[rel]-() delete node, rel