Java 适配neo4j图数据库并控制节点增删改查
·
环境准备
- 开发工具与依赖:JDK 8+、Maven、Neo4j 3及以上(作者使用版本为3.5.35)。
- neo4j 浏览器可视化地址端口:
7474,服务端口:7687,默认账户密码:neo4j/neo4j pom引入 Neo4j Java 驱动依赖(如org.neo4j.driver)。- Java yml文件 spring.data.neo4j 配置 Neo4j 连接参数(URI、用户名、密码)。
spring:
data:
neo4j:
uri: bolt://localhost:7687
username: neo4j
password: 123456
参考官网
neo4j 图数据库连接管理工具类
示例代码:
import org.neo4j.driver.*;
import org.neo4j.driver.types.Node;
import org.neo4j.driver.types.Relationship;
/**
* neo4j 图数据库连接管理工具类
*/
public class Neo4jGraphUtils {
//neo4j服务驱动
static Driver driver;
/**
* 获取neo4j连接
* @param boltUrl neo4j bolt地址
* @param user 用户名
* @param password 密码
*/
public void getNeo4jDriver(String boltUrl,String user,String password) {
driver = GraphDatabase.driver(boltUrl, AuthTokens.badic(user,password));
}
//关闭连接
public static void closeNeo4j() {
if(driver != null){
driver.close();
}
}
/**
* 添加节点
* @param node 节点名称
* @param properties 节点属性信息
*/
public static void addNode(String node ,String properties ) {
try(Session session = driver.session()){
String cypher = "Merge (a:"+node+" "joinMap(properties)+")";
session.writeTransaction(tx -> tx.run(cypher));
}catch(Exception e){
e.printStacktrace();
}
}
/**
* 添加节点联系关系
* @param node 节点名称数组
* @param nodePropertyShip 节点属性 关联字段数组
* @param relationshipType 联系关系类型名称
* @param relationship 联系关系属性内容
*/
public static void addRelationship(String[] node ,String[] nodePropertyShip,String relationshipType ,Map<String,Object> relationship) {
try(Session session = driver.session()){
String relationshipStr = ObjectUtils.isEmpty(relationship) ? relationshipType : relationshipType + " " + joinMap(relationship);
String cypher = "MATCH (n1:"+node[0]+"),(n2:"+node[1]+") WHERE n1.+nodePropertyShip[0]+" = n2.nodePropertyShip[1]+
" CREATE (n1)-[: lx_"+relationshipStr+"]->(n2)";
session.writeTransaction(tx -> tx.run(cypher));
}catch(Exception e){
e.printStacktrace();
}
}
/**
* 删除节点
* @param node 节点名称
*/
public static void deleteNodeAll(String node) {
try(Session session = driver.session()){
//删除节点 保留关系
String cypher = "Merge (n:"+node+" ) delete n ";
session.writeTransaction(tx -> tx.run(cypher));
}catch(Exception e){
e.printStacktrace();
}
}
/**
* 删除连线关系
* @param ship 连线关系名称
*/
public static void deleteShipAll(String ship) {
try(Session session = driver.session()){
String cypher = "Merge (n)-[r: "+ship+" ]-() delete r ";
session.writeTransaction(tx -> tx.run(cypher));
}catch(Exception e){
e.printStacktrace();
}
}
/**
* 删除节点和连线关系
* @param node 节点名称
*/
public static void deleteNodeAll(String node) {
try(Session session = driver.session()){
//去除 detach 关系
String cypher = "Merge (n:"+node+" ) detach delete n ";
session.writeTransaction(tx -> tx.run(cypher));
}catch(Exception e){
e.printStacktrace();
}
}
/**
* 获取节点和连线关系信息
* @param mainNode 主表节点
* @param mainNodePropertyName 主表节点属性名称
* @param mainNodePropertyId 主表节点属性id
* @param level 查询最大层级数
*/
public static List<Map<String,Object>> getNodesInfo(String mainNode,String mainNodePropertyName,String mainNodePropertyId ,String cypher,String level) {
List<Map<String,Object>> result = new ArrayList<>();
Set<Map<String,Object>> set;
try(Session session = driver.session()){
//校验未传cypher时,按前面参数赋值
if(StringUtils.isEmpty(cypher)) {
if(StringUtils.isEmpty(level)) {
//默认查询全部
level = “”;
}
cypher = "match (n:"+mainNode+" {"+mainNodePropertyName+":\""+mainNodePropertyId+“\"})-[r*0.."+level+"]-(n1) return n,r,n1";
}
//执行cypher语句后 遍历结果
session.run(cypher).forEachRemaining(record ->{
//获取节点、联系信息key
List<String> keys = record.keys();
for(String key : keys){
//处理节点关系信息获取
if(key.contains("r")){
if(ObejctUtils.isEmpty(record.get(key))){
continue;
}
for(int i=0;i<record.get(key).size();i++){
Relationship relationship = record.get(key).get(i).asRelationship();
long relId = relationship.id();
String type = relationship.type();
long startNodeId = relationship.startNodeId();
long endNodeId = relationship.endNodeId();
Map<String,Object> relProperties = relationship.asMap();
Map<String,Object> resultMap = new HashMap<>();
resultMap.put("id",relId);
resultMap.put("type","relationship");
resultMap.put("zstpShowName",relProperties.get("关系").toString());
resultMap.put("startNodeId",startNodeId);
resultMap.put("endNodeId",endNodeId);
resultMap.put("properties",relProperties);
result.add(resultMap);
}
continue;
}
//处理节点信息获取
Node node = record.get(key).asNode();
long nodeId = node.id();
List<String> labels = (List<String) node.labels();
Map<String,Object> nodeProperties = node.asMap();
Map<String,Object> resultMap = new HashMap();
resultMap.put("id",nodeId);
resultMap.put("ty1pe","node");
//获取预览回显值
String zszdLabel = nodeProperties.get("zszdLabel").toString();
resultMap.put("zstpShowName",nodeProperties.get(zszdLabel).toString());
resultMap.put("properties",nodeProperties);
result.add(resultMap);
}
});
}catch(Exception e){
e.printStacktrace();
}finally{
//去重
set = new HashSet<>(result);
List<Map<String,Object>> noDuplicateList = new ArrayList<>(set);
return noDuplicateList;
}
}
//map转str 适配neo4j格式
public static <K,V> String joinMap(Map<K,V> map){
if(map == null || map.isEmpty()) return "";
StringBuilder sb = new StringBuilder();
sb.append("{");
boolean firstEntry = true;
for(Map.Entry<K,V> entry : map.entrySet()){
K key = entry.getKey();
V value = entry.getValue();
// 如果不是第一个条目,添加逗号
if(!firstEntry){
sb.append(",");
}else{
firstEntry = false;
}
// 添加键和值,并将=替换成:
sb.append(key).append(":").append("\""+value+"\"");
}
sb.append("}");
return sb.toString();
}
/**
*
* 获取节点最大层级数
* @param mainNode 主表节点
* @param mainNodePropertyName 主表节点属性名称
* @param mainNodePropertyId 主表节点属性id
*/
public static Integer getNodeMaxLevel(String mainNode,String mainNodePropertyName,String mainNodePropertyId){
//返回结果信息
final Integet[] maxLevel = new Integer[1];
try(Session session = driver.session()){
//执行最大层级数查询
String cypher = "match (n:"+mainNode+" {"+mainNodePropertyName+":\""+mainNodePropertyId+"\"})-[r*0..]-(n1) return max(length(r)) as level";
//执行cypher语句后 遍历结果
session.run(cypher).forEachRemaining(record ->{
maxLevel[0] = Integer.parseInt(record,values().get(0).toString());
);
}catch(Exception e){
e.printStacktrace();
}
return maxLevel[0];
}
常见Cypher语句
- 删除所有关系
MATCH (n)-[r]-() DELETE r
MATCH (n)-[r:指定关系名]-() DELETE r - 删除所有节点 (DETACH 先将所有与该节点相连的边(relationship)从图数据库中移除然后再进行节点本身的删除操作)
MATCH (n) DETACH DELETE n
MATCH (n:Person) DETACH DELETE n - 添加节点(该节点存在则不更改,否则新建并返回)
MERGE (p:Person {id:521,name:"李四"}) RETURN p//3.5.35用MATCH 4.4.36版本使用MERGE - 添加关系
MATCH (n:Person {name:"张三"}),(p:Movie {名称:"魔幻手机"}) CREATE (u)-[:看过]->(p)
MATCH (n:Person {name:"张三"}),(p:Movie {名称:"魔幻手机"}) WHERE n.id = p.nId CREATE (u)-[:看过]->(p)
//下面俩是4.4.36版本使用
MERGE (n:Person {name:"张三"}) MERGE (p:Movie {name:"魔幻手机"}) MERGE (n)-[:看过]->(p) // 关系已存在则不创建,不存在则创建 RETURN n, p;
CREATE (n:Person {name:"李四"})-[:看过]->(p:Movie {name:"魔幻手机"})//都是新创建的 - 查看全部节点及关系
MATCH (n) RETURN n LIMIT 10 - 查看指定条件的节点及关系
MATCH (n:Person {name:"张三"})-[r:看过]->(m:Movie) return n,r,m - 查看某一实体节点开始的深度遍历 无层级限制的深度遍历 1…1是从第几层到第几层
MATCH (n:Person {id:"2"})-[r*0..]-(n1) return n,r,n1
MATCH (n:Person {id:"2"})-[r*1..1]-(n1) return n,r,n1 - 获取某一节点开始往下深度遍历最大的层级数
MATCH (n:Person {id:"2"})-[r*0..]-(n1) return max(length(r))
MATCH p=(n:Movie {名称:"魔幻手机"})-[*0..]-(n1) RETURN max(length(p)) AS max_path_length;// 4.4.36版本使用 - 查看所有节点名称标签
MATCH (n) RETURN DISTINCT labels(n) - 查看所有关系名称
MATCH ()-[r]-() RETURN DISTINCT type(r) - 修改节点属性
MATCH (n:Person {id:"2"}) SET n.age=30 RETURN n - 条件存在则修改 否则新增
MERGE (p:Person {name: "Alice"}) ON CREATE SET p.created = timestamp(), p.age = 25, p.status = "new" ON MATCH SET p.lastSeen = timestamp(), p.status = "updated" RETURN p.name, p.age, p.status, p.created, p.lastSeen
更多推荐



所有评论(0)