Neo4j学习实录 下载-安装-springboot操作neo4j

由于课程作业的原因,今天简单学习了一下Neo4j数据库。

下载和安装很简单,去官网下载即可

基本元素的介绍

节点:表示一个实体记录,就像关系数据库当中一条记录。一个节点包含多个属性和标签

 

关系:关系用于将节点关联起来构成图,关系也称为图论的边

 

属性:节点和关系都可以有多个属性。属性由键值对组成,就像哈希

 

标签:指示一组拥有相同属性的节点,但不强制要求相同,一个节点可以有多个标签

 

路径:图中任意俩个节点都存在由关系组成的路径

 

Neo4j的操作语句借鉴了sql,基本语法有点相似

CQL代表Cypher查询语言。 像Oracle数据库具有查询语言SQL,Neo4j具有CQL作为查询语言。

Neo4j CQL -

  • 它是Neo4j图形数据库的查询语言。

  • 它是一种声明性模式匹配语言

  • 它遵循SQL语法。

  • 它的语法是非常简单且人性化、可读的格式。

增加节点-- create

create (book:Book)

删除节点 delete

MATCH (n:`孙鹏翔`) delete n

修改 set

MATCH (book:Book) SET book.title = '红楼梦' RETURN book

 我们可以看到book节点的属性中有了title

 

查询 match

实际上所有的操作基本都是基于查询的,只有先查到才能进行增删改

 

 

Neo4j的模板数据

 这三个分别是不同的模板数据,相当于一个官方教程,第一个是语句创建图形数据,第二个是读取csv文件创建,第三个是查询数据的模板

可以通过这三个来深入理解Neo4j的使用

小知识:Neo4j的前端展示是通过d3.js来实现的。

注意:后面springboot整合Neo4j操作的数据就是第一个模板数据

SpringBoot操作Neo4j

第一步:引入依赖(使用maven)

pom.xml

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>1.4.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test-autoconfigure</artifactId>
</dependency>
<!-- thymeleaf依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>

 第二步 yml的配置

server:
port: 8888
neo4j:
url: bolt://127.0.0.1:7687
username: neo4j
password: 123456
第三步 Neo4j驱动配置

Neo4jConf.java 

package com.mn.springboot.utils;

import org.neo4j.driver.v1.AuthTokens;
import org.neo4j.driver.v1.Driver;
import org.neo4j.driver.v1.GraphDatabase;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* neo4j配置
*/
@Configuration
public class Neo4jConf {
@Value("${neo4j.url}")
private String url;
@Value("${neo4j.username}")
private String username;
@Value("${neo4j.password}")
private String password;

@Bean(name = "driver")
public Driver initDriver() {
Driver driver;
try {
driver = GraphDatabase.driver(url, AuthTokens.basic(username, password));
} catch (Exception e) {
throw new RuntimeException(e);
}
return driver;
}
}
第四步 工具类

实际上就相当于mapper/dao 层,与数据库进行交互,操作Neo4j数据库,对数据进行封装

package com.mn.springboot.utils;

import org.neo4j.driver.internal.InternalNode;
import org.neo4j.driver.internal.InternalRelationship;
import org.neo4j.driver.v1.*;
import org.neo4j.driver.v1.types.Node;
import org.neo4j.driver.v1.types.Path;
import org.neo4j.driver.v1.types.Relationship;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

/**
* 通用的neo4j调用类
*
* @version 1.0 18-6-5 上午11:21
*/
@Component
public class Neo4jUtil {
private static Driver driver;

@Autowired
public Neo4jUtil(Driver driver) {
Neo4jUtil.driver = driver;
}

/**
* cql的return返回多种节点match (n)-[edge]-(n) return n,m,edge:限定返回关系时,关系的别名必须“包含”edge
* @param cql 查询语句
* @param lists 和cql的return返回节点顺序对应
* @return List<Map<String,Object>>
*/
public static <T> void getList(String cql, Set<T>... lists) {
//用于给每个Set list赋值
int listIndex = 0;
try {
Session session = driver.session();
StatementResult result = session.run(cql);
List<Record> list = result.list();
for (Record r : list) {
if (r.size() != lists.length) {
System.out.println("节点数和lists数不匹配");
return;
}
}
for (Record r : list) {
for (String index : r.keys()) {
//对于关系的封装
if (index.indexOf("edge") != -1) {
Map<String, Object> map = new HashMap<>();
//关系上设置的属性
map.putAll(r.get(index).asMap());
//外加三个固定属性
map.put("edgeId", r.get(index).asRelationship().id());
map.put("edgeFrom", r.get(index).asRelationship().startNodeId());
map.put("edgeTo", r.get(index).asRelationship().endNodeId());
lists[listIndex++].add((T) map);
}
//对于节点的封装
else {
Map<String, Object> map = new HashMap<>();
//关系上设置的属性
map.putAll(r.get(index).asMap());
//外加一个固定属性
map.put("nodeId", r.get(index).asNode().id());
lists[listIndex++].add((T) map);
}
}
listIndex = 0;
}
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* cql 路径查询 返回节点和关系
* @param cql 查询语句
* @param nodeList 节点
* @param edgeList 关系
* @return List<Map<String,Object>>
*/
public static <T> void getPathList(String cql, Set<T> nodeList, Set<T> edgeList) {
try {
Session session = driver.session();
StatementResult result = session.run(cql);
List<Record> list = result.list();
for (Record r : list) {
for (String index : r.keys()) {
Path path = r.get(index).asPath();
//节点
Iterable<Node> nodes = path.nodes();
for (Iterator iter = nodes.iterator(); iter.hasNext(); ) {
InternalNode nodeInter = (InternalNode) iter.next();
Map<String, Object> map = new HashMap<>();
//节点上设置的属性
map.putAll(nodeInter.asMap());
//外加一个固定属性
map.put("nodeId", nodeInter.id());
nodeList.add((T) map);
}
//关系
Iterable<Relationship> edges = path.relationships();
for (Iterator iter = edges.iterator(); iter.hasNext(); ) {
InternalRelationship relationInter = (InternalRelationship) iter.next();
Map<String, Object> map = new HashMap<>();
map.putAll(relationInter.asMap());
//关系上设置的属性
map.put("edgeId", relationInter.id());
map.put("edgeFrom", relationInter.startNodeId());
map.put("edgeTo", relationInter.endNodeId());
edgeList.add((T) map);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* cql 返回具体的属性, 如match (n)-[]-() return n.id,n.name,match (n)-[]-() return count(n)
* @param cql 查询语句
* @return List<Map<String,Object>>
*/
public static List<Map<String, Object>> getFields(String cql) {
List<Map<String, Object>> resList = new ArrayList<>();
try {
Session session = driver.session();
StatementResult result = session.run(cql);
List<Record> list = result.list();
for (Record r : list) {
resList.add(r.asMap());
}
} catch (Exception e) {
e.printStackTrace();
}
return resList;
}

/**
* 执行添加cql
* @param cql 查询语句
*/
public static void add(String cql) {
//启动事务
try (Session session = driver.session();
Transaction tx = session.beginTransaction()) {
tx.run(cql);
//提交事务
tx.success();
} catch (Exception e) {
e.printStackTrace();
}
}
}
第五步 controller开发
package com.mn.springboot.controller;

import com.mn.springboot.utils.Neo4jUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

@RestController
public class TestController {
@Autowired
private Neo4jUtil neo4jUtil;

@GetMapping("get")
public Map<String, Object> get() {
Map<String, Object> retMap = new HashMap<>();
//cql语句
String cql = "match (m:Person{name: "Meg Ryan"}) return m";
Set<Map<String, Object>> nodeList = new HashSet<>();
neo4jUtil.getList(cql, nodeList);
retMap.put("nodeList", nodeList);
return retMap;
}
controller层用于与前端交互,进行数据展示,这里只写了简单的get方法,进行一波测试,后面增删改查自由扩展
get请求查询的结果,实际开发中我们要用postman或者swagger进行接口测试,这里我就偷懒了。
 
原文地址:https://www.cnblogs.com/spx88/p/14144888.html