neo4j学习笔记

neo4j - note

一、概述

1.链接

官网: https://neo4j.com/

官网document: https://neo4j.com/docs/getting-started/current/

官网下载: https://neo4j.com/download-center/

官网指令操作指南: https://neo4j.com/docs/cypher-manual/current/clauses/

文字教程: http://www.vue5.com/neo4j/neo4j_exe_environment_setup.html

w3school: https://www.w3cschool.cn/neo4j/ 推荐这个文字教程

B站教程: https://www.bilibili.com/video/BV1HQ4y1h78j/?spm_id_from=333.337.search-card.all.click 讲得不太好,可以看文字教程即可

spring-data neo4j: https://spring.io/projects/spring-data-neo4j#learn

spring-data neo4j: https://neo4j.com/developer/spring-data-neo4j/

2.介绍

百度百科的明星关系

银行欺诈检测

反洗钱

供应链管理

与MYSQL对比

MYSQLNEO4J
节点
列和数据属性和数据
约束关系
数据模型

属性图模型规则

  • 代表节点,关系和属性中的数据
  • 节点和关系都包含属性
  • 关系连接节点
  • 属性是键值对
  • 节点使用圆圈表示,关系用箭头键表示。
  • 关系有方向:单向和双向。
  • 每个关系包含“起始节点”或“从节点”和“到节点”或“结束节点”

构件:

  • 节点
  • 属性
  • 关系
  • 标签
  • 数据浏览器,浏览器打开数据库

二、使用

1.环境搭建

如果neo4j.4.X + 的版本要当前jvm环境是 jdk 11

下载3.x的最高版本

设置NEO4J_HOME = C: neo4j-community-2.1.3

设置PATH = C: neo4j-community-2.1.3 bin;

启动控制台

neo4j console  

desktop客户端也可以操作,推荐,客户端可以安装不同版本的 server

http://localhost:7474/

初始用户名和密码 neo4j

登录后会要求改密码 123456

2.CQL

CQL命令/条用法
CREATE 创建创建节点,关系和属性
MATCH 匹配检索有关节点,关系和属性数据
RETURN 返回返回查询结果
WHERE 哪里提供条件过滤检索数据
DELETE 删除删除节点和关系
REMOVE 移除删除节点和关系的属性
ORDER BY以…排序排序检索数据
SET 组添加或更新标签
1. 创建 Create
语法元素描述
CREATE它是一个Neo4j CQL命令。
它是我们要创建的节点名称。
它是一个节点标签名称
CREATE (dept:Dept)   无属性

语法说明:

语法元素描述
它是我们将要创建的节点名称。
它是一个节点标签名称
属性是键值对。 定义将分配给创建节点的属性的名称
属性是键值对。 定义将分配给创建节点的属性的值
带属性节点
CREATE (
   <node-name>:<label-name>
   { 	
      <Property1-name>:<Property1-Value>
      ........
      <Propertyn-name>:<Propertyn-Value>
   }
)

CREATE (dept:Dept {deptno:10,dname:"Accounting",location:"Hyderabad" })
CREATE (emp:Employee{id:123,name:"Lokesh",sal:35000,deptno:10})
CREATE (m:Dept:Employee{id:138})  #创建m节点,对应多个标签
2. 查询Match
  • 从数据库获取有关节点和属性的数据
  • 从数据库获取有关节点,关系和属性的数据
MATCH 
(
   <node-name>:<label-name>
)
#获取25个节点
MATCH (n) RETURN n LIMIT 25

# 查询Dept下的内容
MATCH (dept:Dept) return dept

# 查询Employee标签下 id=123,name="Lokesh"的节点
MATCH (p:Employee {id:123,name:"Lokesh"}) RETURN p

## 查询Employee标签下name="Lokesh"的节点,使用(where命令)
MATCH (p:Employee)
WHERE p.name = "Lokesh"
RETURN p

## 返回lin的关联关系及节点
match p=(:Employee{name:"lin"}) -[r:HAVE]->() return p 

## 查询neo4j帮我们自动生成的<id>
MATCH (n:Dept) where id(n)=42 RETURN n LIMIT 25
3. Return
需要搭配查询语句match,不可单独用
RETURN 
   <node-name>.<property1-name>,
   ........
   <node-name>.<propertyn-name>
   
return n 返回整个节点
return n.deptno 就返回n的属性  

MATCH (dept: Dept) RETURN dept.deptno,dept.dname,dept.location
4. 关系基础-创建

基于方向性,Neo4j关系被分为两种主要类型。

  • 单向关系
  • 双向关系

在以下场景中,我们可以使用Neo4j CQL CREATE命令来创建两个节点之间的关系。 这些情况适用于Uni和双向关系。

  • 在两个现有节点之间创建无属性的关系
  • 在两个现有节点之间创建有属性的关系
  • 在两个新节点之间创建无属性的关系
  • 在两个新节点之间创建有属性的关系
  • 在具有WHERE子句的两个退出节点之间创建/不使用属性的关系
CREATE (cc:CreditCard{id:"5001",number:"1234567890",cvv:"888",expiredate:"20/17"})
CREATE (e:Customer{id:"1001",name:"Abc",dob:"01/10/1982"})
MATCH (<node1-label-name>:<nodel-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>
(1) 现有节点之间创建无属性的关系

客户指向信用卡

MATCH (e:Customer),(cc:CreditCard) 
CREATE (e)-[r:DO_SHOPPING_WITH ]->(cc) 

查询

MATCH (e)-[r:DO_SHOPPING_WITH ]->(cc)  RETURN r   #返回单纯的关系

MATCH p=()-[r:DO_SHOPPING_WITH]->() RETURN p  #返回这个关系所连接的所有节点
(2) 现有节点之间创建有属性的关系
MATCH (cust:Customer{name:"lin"}),(cc:CreditCard) 
CREATE (cust)-[r:DO_SHOPPING_WITH_PROP{shopdate:"12/12/2014",price:55000}]->(cc) 
RETURN r
MATCH (cust:Customer{name:"lin"}),(cc:CreditCard),(r:Relation) 
where r.form=cust.name
CREATE (cust)-[r:DO_SHOPPING_WITH_PROP{shopdate:"12/12/2014",price:55000}]->(cc) 
RETURN r
(3) 新节点之间创建无属性的关系
# LIKES关系标签  like关系名称,一般写r即可
CREATE (fb1:FaceBookProfile1)-[like:LIKES]->(fb2:FaceBookProfile2) 

查询关系

MATCH (fb1:FaceBookProfile1)-[like:LIKES]->(fb2:FaceBookProfile2) 
RETURN like

MATCH (e)-[r:LIKES ]->(cc)  RETURN r
(4) 新节点之间创建有属性的关系
CREATE (video1:YoutubeVideo1{title:"Action Movie1",updated_by:"Abc",uploaded_date:"10/10/2010"})
-[movie:ACTION_MOVIES{rating:1}]->
(video2:YoutubeVideo2{title:"Action Movie2",updated_by:"Xyz",uploaded_date:"12/12/2012"}) 
MATCH p=()-[r:ACTION_MOVIES]->() RETURN p LIMIT 25

MATCH (video1)-[r:ACTION_MOVIES]->(video2) 
RETURN video1,video2
(5) 检索关系节点的详细信息 用这个
MATCH (cust)-[r:DO_SHOPPING_WITH]->(cc) 
RETURN cust,cc
5. where子句

AND RO NOT

MATCH (emp:Employee) 
WHERE emp.name = 'Abc' OR emp.name = 'Xyz'
RETURN emp
# WHERE子句在两个现有节点之间创建了一个NEW关系
MATCH (cust:Customer),(cc:CreditCard) 
WHERE cust.id = "1001" AND cc.id= "5001" 
CREATE (cust)-[r:DO_SHOPPING_WITH{shopdate:"12/12/2014",price:55000}]->(cc) 
RETURN r
6. delete删除(节点和关系)
  • 删除节点。
  • 删除节点及相关节点和关系。

删除节点

MATCH (e: Employee) DELETE e

删除节点和关系

MATCH (cc: FaceBookProfile1)-[rel]-(c:FaceBookProfile2) 
DELETE cc,c,rel

删除关系

MATCH (cc: CreditCard)-[rel]-(c:Customer) 
DELETE rel
7. remove删除(标签和属性)
  • 删除节点或关系的标签
  • 删除节点或关系的属性
CREATE (book:Book {id:122,title:"Neo4j Tutorial",pages:340,price:250}) 

MATCH (book : Book)
RETURN book
删除属性
MATCH (book { id:122 })
REMOVE book.price
RETURN book

类似于SQL 
ALTER TABLE BOOK REMOVE COLUMN PRICE;
SELECT * FROM BOOK WHERE ID = 122;
删除多标签节点 中的一个标签
MATCH (m:Employee) where m.id=138
REMOVE m:Dept
8. set子句更新

向现有节点或关系添加新属性

MATCH (n:YoutubeVideo1)
set n.updated_by='lin'
return n
9. roder/limit/union/skip

order by

MATCH (emp:Employee)
RETURN emp.empid,emp.name,emp.salary,emp.deptno
ORDER BY emp.name DESC

union 它将两组结果中的公共行组合并返回到一组结果中。 它不从两个节点返回重复的行。

MATCH (cc:CreditCard)
RETURN cc.id as id,cc.number as number,cc.name as name,
   cc.valid_from as valid_from,cc.valid_to as valid_to
UNION
MATCH (dc:DebitCard)
RETURN dc.id as id,dc.number as number,dc.name as name,
   dc.valid_from as valid_from,dc.valid_to as valid_to

union all 它结合并返回两个结果集的所有行成一个单一的结果集。它还返回由两个节点重复行。

MATCH (cc:CreditCard)
RETURN cc.id as id,cc.number as number,cc.name as name,
   cc.valid_from as valid_from,cc.valid_to as valid_to
UNION ALL
MATCH (dc:DebitCard)
RETURN dc.id as id,dc.number as number,dc.name as name,
   dc.valid_from as valid_from,dc.valid_to as valid_to

limit skip

MATCH (emp:Employee) 
RETURN emp
LIMIT/SKIP 2
10.合并
MERGE = CREATE + MATCH

MERGE命令检查该节点在数据库中是否可用。 如果它不存在,它创建新节点。 否则,它不创建新的

MATCH  (gp2:GoogleProfile2) 
RETURN gp2.Id,gp2.Name
11.NULL值 / IN
MATCH (e:Employee) 
WHERE e.id IS 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

3.函数

字符串函数
描述
UPPER它用于将所有字母更改为大写字母。
LOWER它用于将所有字母改为小写字母。
SUBSTRING它用于获取给定String的子字符串。
REPLACE它用于替换一个字符串的子字符串。
MATCH (e:Employee) 
RETURN e.id,UPPER(e.name),e.sal,e.deptno

MATCH (e:Employee) 
RETURN e.id,SUBSTRING(e.name,0,2),e.sal,e.deptno
聚合函数
聚集功能描述
COUNT它返回由MATCH命令返回的行数。
MAX它从MATCH命令返回的一组行返回最大值。
MIN它返回由MATCH命令返回的一组行的最小值。
SUM它返回由MATCH命令返回的所有行的求和值。
AVG它返回由MATCH命令返回的所有行的平均值。
MATCH (e:Employee) RETURN COUNT(*)

MATCH (e:Employee) 
RETURN MAX(e.sal),MIN(e.sal)

MATCH (e:Employee) 
RETURN SUM(e.sal),AVG(e.sal)
关系函数
描述
STARTNODE它用于知道关系的开始节点。
ENDNODE它用于知道关系的结束节点。
ID它用于知道关系的ID。
TYPE它用于知道字符串表示中的一个关系的TYPE。
MATCH (a)-[movie:ACTION_MOVIES]->(b) 
RETURN STARTNODE(movie)

MATCH (a)-[movie:ACTION_MOVIES]->(b) 
RETURN ENDNODE(movie)

MATCH (a)-[movie:ACTION_MOVIES]->(b) 
RETURN ID(movie),TYPE(movie)

4.索引

CREATE INDEX ON :<label_name> (<property_name>)

CREATE INDEX ON :Customer (name)
DROP INDEX ON :<label_name> (<property_name>)

DROP INDEX ON :Customer (name)

5.UNIQUE约束

CREATE CONSTRAINT ON (cc:CreditCard)
ASSERT cc.number IS UNIQUE
DROP CONSTRAINT ON (cc:CreditCard)
ASSERT cc.number IS UNIQUE

三、代码运用

1. spring data neo4j 5.x

参考spring官网

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-neo4j</artifactId>
             <version>2.3.6.RELEASE</version>
</dependency>

新版本替换了下面的注解

    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-neo4j</artifactId>
      <version>5.3.5.RELEASE</version>
      <scope>compile</scope>
    </dependency>

使用5.x版本 是下面的Old 如果是6.x版本关系不好理解,且官网文档写不清楚关系如何连接

OldNew
org.neo4j.ogm.annotation.NodeEntityorg.springframework.data.neo4j.core.schema.Node
org.neo4j.ogm.annotation.GeneratedValueorg.springframework.data.neo4j.core.schema.GeneratedValue
org.neo4j.ogm.annotation.Idorg.springframework.data.neo4j.core.schema.Id
org.neo4j.ogm.annotation.Propertyorg.springframework.data.neo4j.core.schema.Property
org.neo4j.ogm.annotation.Relationshiporg.springframework.data.neo4j.core.schema.Relationship
(1) node
package com.lin.neo4j.domain;

import lombok.Builder;
import lombok.Data;
import org.neo4j.ogm.annotation.GeneratedValue;
import org.neo4j.ogm.annotation.Id;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Property;

@Data
@Builder
@NodeEntity("Dept") // 标签:默认就是类名
public class Dept {
    @Id // 声明主键
    @GeneratedValue  // 声明该字段为neo4j自动生成的<id>映射的字段
    private Long id;

    @Property("deptno") // 如果名称不一样可用
    private Integer deptno;

    private String dname;

    private String location;
}
@Data
@NodeEntity
public class Person {
    @Id
    @GeneratedValue
    private Long id;

    private String name;
}
import lombok.Data;
import org.neo4j.ogm.annotation.EndNode;
import org.neo4j.ogm.annotation.GeneratedValue;
import org.neo4j.ogm.annotation.Id;
import org.neo4j.ogm.annotation.RelationshipEntity;
import org.neo4j.ogm.annotation.StartNode;

/**
 * 部门关系
 */
@Data
@RelationshipEntity(type = "DeptRelationShip")
public class DeptRelationShip {
    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @StartNode
    private Dept startNode;

    @EndNode
    private Person endNode;
}
(2) repository
import com.lin.neo4j.domain.Dept;

import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface DeptRepository extends Neo4jRepository<Dept,Long> {

    @Query(value = "create (d:Dept {deptno:{0},dname:{1},location:{2}})")
    void create(Integer deptno, String dname, String location);

    Dept findByDeptno(Integer deptno);

    List<Dept> findByDeptnoOrderByDeptnoAsc(Integer deptno);

}

@Repository
public interface DeptRelationRepository extends Neo4jRepository<DeptRelationShip, Long> {

}
  List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);

  // Enables the distinct flag for the query
  List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);
  List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname);

  // Enabling ignoring case for an individual property
  List<Person> findByLastnameIgnoreCase(String lastname);
  // Enabling ignoring case for all suitable properties
  List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname);

  // Enabling static ORDER BY for a query
  List<Person> findByLastnameOrderByFirstnameAsc(String lastname);
  List<Person> findByLastnameOrderByFirstnameDesc(String lastname);
Page<User> findByLastname(String lastname, Pageable pageable);

Slice<User> findByLastname(String lastname, Pageable pageable);

List<User> findByLastname(String lastname, Sort sort);

List<User> findByLastname(String lastname, Pageable pageable);


Sort sort = Sort.by("firstname").ascending()
  .and(Sort.by("lastname").descending());

limit

User findFirstByOrderByLastnameAsc();

User findTopByOrderByAgeDesc();

Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);

Slice<User> findTop3ByLastname(String lastname, Pageable pageable);

List<User> findFirst10ByLastname(String lastname, Sort sort);

List<User> findTop10ByLastname(String lastname, Pageable pageable);

组合结果

interface PersonRepository extends Repository<Person, Long> {
  Streamable<Person> findByFirstnameContaining(String firstname);
  Streamable<Person> findByLastnameContaining(String lastname);
}

Streamable<Person> result = repository.findByFirstnameContaining("av")
  .and(repository.findByLastnameContaining("ea"));
(3) operate实践
@SpringBootTest(classes = Application.class)
@RunWith(SpringRunner.class)
public class NodeTest {
    @Autowired
    private DeptRepository deptRepository;

    @Test
    public void testCreate() {
       deptRepository.create(6,"技术部","深圳");
       deptRepository.save(Dept.builder().deptno(3).dname("人力资源").location("广州").build());
    }

    @Test
    public void testDelete() {
        // 这里的删除有关系也能删除掉
        deptRepository.deleteById(40L);
    }

    @Test
    public void testDeptQuery() {
        final Iterable<Dept> all = deptRepository.findAll();
        all.forEach(e-> System.out.println(e));
        System.out.println(deptRepository.findById(40L));
    }

    @Test
    public void testDeptNativeQuery() {
        Dept deptn = deptRepository.findByDeptno(4);
        System.out.println(deptn);
        System.out.println(deptRepository.findByDeptno(4));
    }
}
@SpringBootTest(classes = Application.class)
@RunWith(SpringRunner.class)
public class RelationTest {
    @Autowired
    private DeptRepository deptRepository;

    @Autowired
    private DeptRelationRepository deptRelationRepository;

    @Test
    public void testRelation() {
        DeptRelationShip deptRelationShip = new DeptRelationShip();
        deptRelationShip.setName("归属");

        Dept dept = deptRepository.findById(86L).orElse(null);
        deptRelationShip.setStartNode(dept);

        Person person = new Person();
        person.setName("霖");
//        person.setId(106L);
        deptRelationShip.setEndNode(person);

        // 这里的保存关系 会连带保存person新节点,如果person设置id且该id已存在,则不新建person节点
        deptRelationRepository.save(deptRelationShip);
    }

    @Test
    public void testRelationQuery() {
        Iterable<DeptRelationShip> deptRelationAll = deptRelationRepository.findAll();
        deptRelationAll.forEach(e-> System.out.println(e));
    }
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值