今天实现Windows版的neo4j画图
本来打算用docker拉取neo4j
安装docker和docker desktop
打不开,需要安装wsl
下载完装不上去,docker desktop一直打不开,可能是有什么冲突,换个方式,直接下载社区版
neo4j
下载地址
https://neo4j.com/deployment-center/
下载时候注意,最新的neo4j是支持Java21的
,我本地电脑安装的是Java11,需要下载4.x版本的neo4j
,也不能下载的太老的版本,否则一些api会不支持
进到bin目录下执行neo4j console
访问
http://localhost:7474/browser/
用户名和密码都是neo4j
注意spring-boot-starter-data-neo4j3.4.0
支持的是Java17
查看springboot的版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.0</version> <!-- Spring Boot 父项目版本 -->
</parent>
报错
错误: 加载主类 org.test.Application 时出现 LinkageError
java.lang.UnsupportedClassVersionError: org/test/Application has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 55.0
springboot版本太高了,springboot3.x对应的是Java17,springboot2.x对应的是Java11
降低springboot的版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version> <!-- Spring Boot 父项目版本 -->
</parent>
如果使用的是 JDK 11,可能需要使用较低版本的 neo4j-java-driver。
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>4.4.6</version> <!-- 适用于 JDK 11 -->
</dependency>
建议使用neo4j-java-driver-spring-boot-starter替换neo4j-java-driver
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver-spring-boot-starter</artifactId>
<version>4.3.6.0</version>
</dependency>
报错
Neo.ClientError.Statement.UnsupportedAdministrationCommand
注意社区版的neo4j不能自行创建数据库,更换配置文件里的数据库名为默认的已经存在的数据库
发送一个请求检测一下
已经可以正常显示刚刚创建的节点
报错
Cypher query text should not be an empty string
检查下关系的cypher写的对不对
报错
invalid input 性质1’: expected an identifier (line 1, column 82 (
我使用的是neo4j4.4.1,关系类型里不能直接使用中文,如果你需要在关系中使用中文描述
MATCH (a:Node),(b:Field)
WHERE a.title = "xxx" AND b.field = "xxx"
CREATE (b)-[r:PROPERTIES {description: "性质1"}]->(a)
没出图可能是ab读顺序不对,a是Node,b是Field
用
MATCH (a:Node {title: "9号"})
RETURN a
检查一下
cypher中查看a.title="XXX"的所有关系图
MATCH (a {title: "xxx"})-[]-(b)
RETURN a, b
具体实现方式
(这里需要给节点去重,所以不适用CREATE,而是MERGE)
springboot使用的2.x版本(不能用3.x,版本太高不兼容会报错
)
需要导入的依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version> <!-- Spring Boot 父项目版本 -->
</parent>
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver-spring-boot-starter</artifactId>
<version>4.3.6.0</version>
</dependency>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
<version>2.7.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
添加neo4数据库连接驱动
import org.neo4j.driver.Driver;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.neo4j.driver.Session;
@Component
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();
}
}
model层,为了区分节点
,创建两个对象
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.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;
}
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
@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;
}
}
具体逻辑实现
import org.springframework.stereotype.Service;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.neo4j.driver.Driver;
import org.neo4j.driver.Session;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Paths;
@Service
public class CsvImporterServiceImpl implements CsvImporterService{
@Autowired
private Driver driver;
private String path = "src/main/resources/csv/";
@Override
public void importData() {
// 先清空所有
Session session = driver.session();
session.run("match (n) detach delete n");
// 顺序最好不要乱 先创建节点 再出创建关系 2和3颠倒无所谓
createNode(path+"2.csv",session);
createNode(path+"3.csv",session);
createNode(path+"1.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/3.csv".equals(filePath)){ // 2
sql = String.format(" MERGE (:Node {title:\"%s\"})", record.get("name"));
}
if("src/main/resources/csv/2.csv".equals(filePath)){ // 3
// 注意这里的节点是Field
sql = String.format(" MERGE (:Field {field:\"%s\"})", record.get("name"));
}
if("src/main/resources/csv/1.csv".equals(filePath)){ // 1
// 这里是创建关系 在创建关系的前提要先创建节点
// 这样会创建出来很多孤岛
//// 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:PROPERTIES {description:\"%s\"}]->(a)",record.get("node1"),record.get("node2"),record.get("label"));
}
// 都放这里执行
System.out.println("sql:"+sql);
session.run(sql);
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
之前可以直接显示中文关系,用的neo4j4.x版本不能直接显示关系,应该可以修改
需要注意不能读错文件
,如果文件读错线就不会显示,如果不确定是不是读对文件就使用
MATCH (a {title: "xxx"})-[]-(b)
RETURN a, b
进行查看
controller层
@GetMapping("/test")
public void test(){
csvImporterService.importData();
}
因为数据量过多,选几个数据进行查询
(数据隐私性较强需要打码)
1.csv
(csv文件逗号分隔,注意第一行)
2.csv
3.csv
代码已经提交到git仓库(test分支
),具体数据已删除,需要自行上传
https://github.com/GreenGeng/neo4jtest/tree/test
先添加远程的仓库
git init
git remote add origin https://github.com/yourusername/your-repo.git
git add .
git commit -m "Initial commit"
git branch // 查看分支
git push origin branch:test
// 修改gitignore
git rm -r --cached .
git add .
git commit -m "Update .gitignore file"
git push origin branch:test
文章同步更新到微信公众号:格鸰爱童话