利用Neo4j的Java驱动获取节点的所有直接关系

利用Neo4j的Java驱动获取节点的所有直接关系

  • 简单介绍
    • 直接上代码
    • 注解
    • 总结

简单介绍

笔者利用Neo4j的Java驱动获取节点的所有直接关系,主要逻辑就是使用驱动查询Neo4j,遍历返回结果的每一条路径,遍历每条路径,从中抽取三元组所有信息
在遍历的过程中,笔者遇到了一些问题,因为笔者要从Neo4j中查取数据,并将其返回至前端,所以获取每条路径中各个元素的信息并存放到Map集合中,并最终打包成JSON对象。
【问题一】:每组路径中都有作为查询条件节点信息,遍历路径时,要避免查询节点重复添加;
【问题二】:将节点的Label也存放到Map对象中,利用节点asMap()返回的map不能中没有节点的Label,需要手动获取并添加

直接上代码

如何添加依赖、依赖的版本请读者看笔者的这篇文章

package com.just.camkg.util;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.neo4j.driver.v1.AuthTokens;
import org.neo4j.driver.v1.Driver;
import org.neo4j.driver.v1.GraphDatabase;
import org.neo4j.driver.v1.Session;
import org.neo4j.driver.v1.StatementResult;
import org.neo4j.driver.v1.Value;
import org.neo4j.driver.v1.types.Node;
import org.neo4j.driver.v1.types.Path;
import org.neo4j.driver.v1.types.Path.Segment;
import org.neo4j.driver.v1.types.Relationship;
import com.alibaba.fastjson.JSONObject;
import org.neo4j.driver.v1.Record;
public class GetNodeAllPath {
	private static Driver driver;
	public static Map<String,Object>nodeMap = new LinkedHashMap(); // 存放所有节点的Map集合
	public static Map<String,Object>relationMap = new LinkedHashMap(); //存放所有关系的Map集合
	public static Map<String, Object> getNodeMap() {
		return nodeMap;
	}
	public static Map<String, Object> getRelationMap() {
	return relationMap;
	}

	//静态代码块,获取驱动 记得修改账户和密码
	static {
		String uri="bolt://localhost:7687";
		String username = "neo4j";
		String password = "liu197917";
		driver = GraphDatabase.driver(uri,AuthTokens.basic(username,password));
	}
	public void close() {
		 driver.close();
	}
	
	// 查询功能
	public void getPathsInfo(String cypher){
		try(Session session = driver.session()){
			StatementResult result = session.run(cypher); // 执行查询语句获取查询结果值
		    Map<String,Object> tempNodeMap =new LinkedHashMap(); //临时存放节点Map
			Map<String,Object> temprelationMap  = new LinkedHashMap(); //临时存放关系Map
			int startHashCode = 0; //起始节点Map的hashCode值,初始值为0
			int endNodeCount = 0;  //查询终止节点的数量
			Node startNode = null;
			Node endNode = null;
			// 遍历Cypher查询结果得到的所有path
			while(result.hasNext()) {
				int tempStartHashCode = startHashCode; // 存放上次的节点的HashCode值
				int tempEndHashCode = endHashCode;
				Record record = result.next();
				List<Value> value = record.values();   //查询记录值
				for(Value i:value){
				Path path = i.asPath();
				startNode = path.start();  // 起始节点
				/* 2 遍历起始节点
				 * 获取起始节点的HashCode值,因为每个三元组都有起始节点,所以利用HashCode值来避免在tempNodeMap中重复添加*/ 
				startHashCode = startNode.hashCode(); 		// 通过节点Hash值去除重复节点
				if (startHashCode!=tempStartHashCode) {

					Map<String,Object> startNodeMap = new LinkedHashMap(); // 获取起始节点的所有属性,并打包成一个Map集合
					// 2.1 解决startNode.asMap().put()方法出错
					for (String key : startNode.asMap().keySet()) {
						startNodeMap.put(key, startNode.asMap().get(key));
					}
					// 2.2 添加节点的类型
					Iterator startNodeTypes = startNode.labels().iterator();
					String startNodeTypeValue = startNodeTypes.next().toString();
					startNodeMap.put("startNodeType", startNodeTypeValue);
					tempNodeMap.put("startNode", startNodeMap);
				}
				/* 3 遍历终止节点*/
				endNode = path.end();
				endHashCode = endNode.hashCode();
				// 这一步起始可以不用添加endHashCode判断,通常路径中只有一个终止节点
					endNodeCount++; 
					Map<String,Object> endNodeMap = new LinkedHashMap();   // 获取终止   节点的所有属性,并打包成一个Map集合
					for(String key : endNode.asMap().keySet()) {
						endNodeMap.put(key, endNode.asMap().get(key));
					}
					Iterator endNodeTypes = endNode.labels().iterator();
					String endNodeTypeValue = endNodeTypes.next().toString();
					endNodeMap.put("endNodeType", endNodeTypeValue);
					tempNodeMap.put("endNode" + endNodeCount, endNodeMap);
		
				
				/* 4 获取路径的关系 */
				String pathType =null;
				Iterable<Relationship> re = path.relationships(); 
				for(Relationship res:re) {
					pathType = res.type(); //路径的关系-用路径关系的类型
					temprelationMap.put("relationShip" + endNodeCount, pathType);
				}
	       }
		}

			this.nodeMap = tempNodeMap;
			this.relationMap = temprelationMap;
	  }
			// this.close(); //关闭驱动 我们希望用户手动关闭,否则只用一次就报错
	}
}

注解

笔者使用的查询语句:

String cypher = "match p= (n:"+ nodeType + ")-[r]->() where n.'" + nodeProperty + " '="+nodePropertyValue +"' return p";
// 其中,nodeType, nodeProperty,nodePropertyValue 分别对应节点类型,节点属性,节点属性值,作为节点定位

笔者是使用Echarts中的关系图来实现知识图谱可视化,所以定制的数据结构为MapnodeMap = new LinkedHashMap(),这样的好处是在遍历数据时,使用put方法保证Map集合数据的顺序。
tempNodeMap.put("startNode", startNodeMap)指明了起始节点,方便前端在JSON中直接取用键名取出数据。
tempNodeMap.put("endNode" + endNodeCount, endNodeMap),目的也是方便前端在JSON中直接用键名取出节点数据,如下面所示:

            var nodeIndex = 1; // 起始节点从1开始
            var relationIndex = 1;
            for (var i =0; i < len; i++) {
              //获取所有的endNode,allInfo是后端返回数据解析出的JSON对象
              if (allInfo["endNode" + nodeIndex] != '{}') {
                endNodeArray.push(allInfo["endNode" + nodeIndex]); // JSON对象中获取所有的endNode
                nodeIndex++;
              }

总结

这是笔者尝试使用节点来查询节点所有路径信息的代码,经测试,可以完成该需求。鉴于笔者时间与能力有限,提供的代码思维逻辑不够清晰,请各位看官多多指正!!基于该方法返回数据结合Echarts实现图谱可视化笔者后续会更新,敬请期待!

你可能感兴趣的:(Neo4j,java,数据库,eclipse)