NEO4j

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
CREATE (
   <node-name>:<label-name1>:<label-name2>....<label-namen>
   {    
      <key>:<Value>,
      ........
      <n-key>:<n-Value>
   }
)
  • 查询 MATCH
MATCH (<node-name>:<label-name1>) return <node-name>.<property1-name>,<node-name>.<property2-name>
  • 条件 WHERE
比较运算符作用
=它是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 删除节点和关系
DELETE <node-name-list>

MATCH (cc: CreditCard)-[rel]-(c:Customer) 
DELETE cc,c,rel
  • remove
    删除节点或关系的标签
    删除节点或关系的属性
MATCH (m:Movie) 
REMOVE m:Pic
  • 添加属性 set
SET  <node-label-name>.<property1-name>,...<node-laben-name>.<propertyn-name>
  • union/union all
MATCH (cc:CreditCard) RETURN cc.id,cc.number
UNION
MATCH (dc:DebitCard) RETURN dc.id,dc.number
  • LIMIT和SKIP子句
// 显示前两行
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>
})
  • null
MATCH (e:Employee) 
WHERE e.id IS NOT NULL
RETURN e.id,e.name,e.sal,e.deptno
  • IN
MATCH (e:Employee) 
WHERE e.id IN [123,124]
RETURN e.id,e.name,e.sal,e.deptno
  • INDEX索引
CREATE INDEX ON :<label_name> (<property_name>)
DROP INDEX ON :<label_name> (<property_name>)
  • UNIQUE约束
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位整数。
floatI用于表示32位浮点数。
double用于表示64位浮点数。
char用于表示16位字符。
String用于表示字符串。

java灵魂代码

  • Spring数据模块的优点:
  • 消除DAO层中的boiler plate代码
  • DAO层中的工件少
  • 易于开发和维护
  • 改进开发过程
  • Spring数据模块功能:
  • 支持基于XML的实体映射
  • 支持基于注释的实体映射
  • 支持分页
  • 支持事务
  • 更少的DAO层工件 - 实现存储库
  • depedency
<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>
  • 新建节点类 java代码
@NodeEntity(label = "Bot")
public class BotNode {
    @Id
    @GeneratedValue
    private Long id; //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 +
                '}';
    }

}
  • 新建节点关系类 java代码
@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 + '\'' +
                '}';
    }
}
  • 创建bean
@Repository
public interface BotRepository extends Neo4jRepository<BotNode,Long> {
    BotNode findAllByName(String name);
    
    //返回节点n以及n指向的所有节点与关系
    @Query("MATCH p=(n:Bot)-[r:BotRelation]->(m:Bot) WHERE id(n)={0} RETURN p")
    List<BotRelation> findAllByBotNode(BotNode botNode);

    //返回节点n以及n指向或指向n的所有节点与关系
    @Query("MATCH p=(n:Bot)<-[r:BotRelation]->(m:Bot) WHERE m.name={name} RETURN p")
    List<BotRelation> findAllBySymptom(@Param("name") String name);

    //返回节点n以及n指向或指向n的所有节点以及这些节点间的所有关系
    @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
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值