Neo4j初探

最近参加了一个小比赛,做的一个自动化工具,并使用neo4j出图谱,最后啥奖也没得到 🐶 菜鸡本菜

早就听说过neo4j图数据库,一直没用过,这次正好有个机会学习一下

初探neo4j

因为本地没有服务器,就打算使用docker运行一个
m2的电脑安装docker

brew install --cask docker

安装好之后去docker的客户端下载客户端

docker官网

拉取neo4j

docker pull neo4j

查看docker 拉取结果

docker images

打开docker客户端之后
在终端运行命令

docker run --publish=7474:7474 --publish=7687:7687 -e 'NEO4J_AUTH=账号/密码' neo4j

账号密码需要修改成自己的~_~
运行之后访问

http://localhost:7474/

即成功在本地搭建好了neo4j 就 可以使用啦

neo4j+springboot2使用

我这里的springboot版本是2.7.4
(neo4j不同版本差异还是很大的,需要注意⚠️,现在我用的这个版本是比较新的,很多注解已经替换不再使用,例如@RelationshipEntity等)

首先需要添加maven依赖

<!-- neo4j 驱动 这个需要自己手动添加一下 -->
<dependency>
    <groupId>org.neo4j.driver</groupId>
    <artifactId>neo4j-java-driver</artifactId>
</dependency>
<!-- neo4j 操作实体注解需要 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>

添加驱动的配置类

public class ExampleCommandLineRunner implements CommandLineRunner {

    private final Driver driver;
    private final ConfigurableApplicationContext applicationContext;
    public final Session session;

    @Bean
    Session session(){
        return session;
    }
    @Override
    public void run(String... args) throws Exception {

    }

    public ExampleCommandLineRunner(Driver driver,ConfigurableApplicationContext applicationContext){
        this.driver = driver;
        this.applicationContext = applicationContext;
        this.session = driver.session();
    }
}

配置文件里需要进行配置

spring.neo4j.uir = bolt://localhost:7687
spring.neo4j.authentication.username = 账号
spring.neo4j.authentication.password = 密码
spring.data.neo4j.database = 库名

创建一个节点

@Node("Person")
@Data
@AllArgsConstructor
@Accessors(chain = true)
public class Person {
    
    @Id
    @GeneratedValue
    private  Long id;
    
    private String name;

}

使用Repository类似JPA操作数据库

@Repository
public interface PersonRepository extends Neo4jRepository<Person,Long> {
}
@Service
public class PersonServiceImpl implements PersonService {
    @Autowired
    private PersonRepository personRepository;
    @Override
    public Person save(Person person) {
        return personRepository.save(person);
    }
}

添加访问层

@RestController
public class PersonController {

    @Autowired
    private PersonService personService;

    @PutMapping("/create")
    public Person create(@RequestBody Person person){
       return personService.save(person);
    }

}

请求结果
请求接口
web进行查看

创建图谱

上面过程即可创建单个节点,接下来就需要创建节点之间的关系
因为关系比较多,所以这里使用的是通过读取csv的方式来创建图谱

先创建csv文件


5.csv
name
小红
小绿
小蓝
小乘
小佳
小鱼
小炎

6.csv
name
木木
飞飞
耿耿
小雪
花花
辰辰
文文
格林
婷婷
green
叶寒
汉威
萌萌

7.csv
node1,node2,label
小红,木木,朋友
小红,飞飞,朋友
小红,耿耿,朋友
小红,小雪,朋友
小红,花花,朋友
小红,辰辰,朋友
小红,小佳,朋友
小绿,木木,亲戚
小绿,格林,亲戚
小绿,叶寒,朋友
小绿,婷婷,朋友
小绿,文文,亲戚
小绿,小雪,朋友
小蓝,木木,朋友
小蓝,辰辰,朋友
小蓝,文文,朋友
小蓝,green,朋友
小蓝,格林,朋友
小乘,飞飞,朋友
小乘,花花,朋友
小乘,文文,朋友
小乘,婷婷,朋友
佳佳,飞飞,朋友
佳佳,木木,朋友
佳佳,辰辰,朋友
佳佳,萌萌,朋友
佳佳,叶寒,朋友
小鱼,小雪,亲戚
小鱼,green,朋友
小鱼,婷婷,朋友
小鱼,汉威,朋友
小鱼,萌萌,朋友
小炎,小雪,仇人
小炎,耿耿,朋友
小炎,花花,朋友
小炎,辰辰,家人
小炎,萌萌,朋友
小炎,小绿,朋友
萌萌,小鱼,朋友
汉威,小绿,朋友
小佳,萌萌,朋友
小绿,green,朋友
小佳,小鱼,朋友
叶寒,文文,朋友

这里有一个比较重要的地方,需要先创建节点,然后再创建关系
实现逻辑的地方
解析csv需要的依赖

 <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-csv</artifactId>
            <version>1.8</version>
        </dependency>

        <dependency>
            <groupId>com.opencsv</groupId>
            <artifactId>opencsv</artifactId>
            <version>3.3</version>
        </dependency>

具体逻辑实现,使用的是session.run(sql)去执行sql语句

 @Autowired
    private Driver driver;
    
@Override
    public void importData() {
        // 先清空所有
        Session session = driver.session();
        session.run("match (n) detach delete n");

        // 顺序最好不要乱 先创建节点 再出创建关系  这里应该是使用单例来写的 比赛时间短 就没有进行优化 直接传入session作为参数 🐶
        createNode(path+"5.csv",session);
        createNode(path+"6.csv",session);
        createNode(path+"7.csv",session);

    }
public void createNode(String filePath,Session session) {
        String sql = "";

        try (Reader reader = Files.newBufferedReader(Paths.get(filePath));
             CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT.withFirstRecordAsHeader().withIgnoreHeaderCase().withTrim());) {
            for (CSVRecord record : csvParser) {
                if("src/main/resources/csv/5.csv".equals(filePath)){ // 2
                    sql = String.format(" CREATE  (:Node {title:\"%s\"})", record.get("name"));
                }
                if("src/main/resources/csv/6.csv".equals(filePath)){ // 3
                    // 注意这里的节点是Field
                    sql = String.format(" CREATE  (:Field {field:\"%s\"})", record.get("name"));
                }
                if("src/main/resources/csv/7.csv".equals(filePath)){ // 1
                    if(record.get("label").equals("朋友")){ //<- belong
            //       这里是创建关系 在创建关系的前提要先创建节点
            //       下面这样会创建出来很多孤岛
                 sql = String.format("CREATE (b:Node {title:\"%s\"}) - [r:belong] -> (a:Node {title:\"%s\"})  ",record.get("node1"),record.get("node2"));
                        sql = String.format(" match(a:Node),(b:Field) where a.title=\"%s\" and b.field=\"%s\" create  (b)-[r:朋友]->(a)",record.get("node1"),record.get("node2"));
                    }

                    if(record.get("label").equals("亲戚")){ // next
                        sql = String.format("match(a:Node),(b:Node) where a.title=\"%s\" and b.title=\"%s\" create  (a)-[r:亲戚]->(b)",record.get("node1"),record.get("node2"));
                    }

                    if(record.get("label").equals("仇人")){ // equal
                        sql = String.format(" match(a:Field),(b:Field) where a.field=\"%s\" and b.field=\"%s\" create  (b)-[r:仇人]->(a)",record.get("node1"),record.get("node2"));
                    }
                }
                // 都放这里执行
                System.out.println("sql:"+sql);
                session.run(sql);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

实体类添加 这里使用的是@Node注解

@Data
@NoArgsConstructor
@Accessors(chain = true)
@Node("Field")
public class FieldEntity {
    @Id
    @GeneratedValue
    private Long id; // 1 2

    private String field;

    public FieldEntity(String fields){
        this.field = fields;
    }

    public FieldEntity(Long id,String fields){
        this.id = id;
        this.field = fields;
    }
}
@Node("Node")
@Data
@AllArgsConstructor
@Accessors(chain = true)
public class NodeEntity {
    @Id
    @GeneratedValue
    private  Long id; // 1 2

    private  String title; 

    public NodeEntity(){}

    public NodeEntity(String title){
        this.title = title;
    }
}

最后的效果图
在这里插入图片描述

总结:
neo4j不同版本之间差异还是挺大的,最新的neo4j的文档还是比较少的,试了很多次最后终于出了简单的图谱 😢

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值