在SqlG中执行广度优先搜索以获取顶点与边信息
问题:使用SqlG执行BFS时无法获取边信息
我正在使用SqlG(Apache TinkerPop针对PostgreSQL的扩展),希望从初始顶点执行广度优先搜索,获取所有顶点及对应的边信息。目前运行的代码仅能获取顶点,无法得到边信息。
创建图的代码
Map<String, String> conf = new HashMap<>(); conf.put("jdbc.url", "jdbc:postgresql://localhost:5432/marko"); conf.put("jdbc.username", "postgres"); conf.put("jdbc.password", "postgres"); Configuration configuration = new MapConfiguration(conf); Graph graph = SqlgGraph.open(configuration); //Creating a usual TinkerPop example Graph graph.traversal().tx().open(); Vertex personMarko = graph.addVertex(T.label, "person", "name", "marko", "age", 29); Vertex personJosh = graph.addVertex(T.label, "person", "name", "josh", "age", 32); Vertex personVadas = graph.addVertex(T.label, "person", "name", "vadas", "age", 27); Vertex personPeter = graph.addVertex(T.label, "person", "name", "peter", "age", 35); Vertex softwareRipple = graph.addVertex(T.label, "software", "name", "ripple", "lang", "java"); Vertex softwareLop = graph.addVertex(T.label, "software", "name", "lop", "lang", "java"); personMarko.addEdge("knows", personJosh, "weight", 1.0); personMarko.addEdge("knows", personVadas, "weight", 0.5); personMarko.addEdge("created", softwareLop, "weight", 0.4); personJosh.addEdge("created", softwareLop, "weight", 0.4); personPeter.addEdge("created", softwareLop, "weight", 0.2); personJosh.addEdge("created", softwareRipple, "weight", 1.0); graph.tx().commit();
原遍历代码(无法获取边)
Vertex start = graph.traversal().V().hasLabel("person").has("name", "marko").next(); graph.traversal().V(start).repeat(__.outE().inV()).emit().path().forEachRemaining(path -> { System.out.println("PATH DETAILS"); for(Object object : path) { if(object instanceof Vertex) { Vertex vertex = (Vertex) object; String name = vertex.value("name") + ""; String label = vertex.label(); System.out.print(String.format("%s[%s] ", name, label)); } if(object instanceof Edge) { //This block is never executed!!! System.out.println("EDGE FOUND"); Edge edge = (Edge) object; String label = edge.label(); System.out.print(String.format("%s ", label)); } } System.out.println("\n"); });
解决方案
问题核心在于原遍历逻辑中,虽然路径经过了边,但元素判断逻辑或遍历写法需要调整,确保边元素被正确识别和捕获。以下是两种可行的修改方案:
方案一:保留完整路径并捕获边信息
调整遍历代码,添加simplePath()避免循环,同时优化元素判断逻辑:
Vertex start = graph.traversal().V().hasLabel("person").has("name", "marko").next(); graph.traversal().V(start) .repeat(__.outE().inV()) .simplePath() // 防止循环遍历重复节点 .emit() .path() .forEachRemaining(path -> { System.out.println("PATH DETAILS"); for (Object object : path) { if (object instanceof Vertex) { Vertex vertex = (Vertex) object; String name = vertex.value("name").toString(); String label = vertex.label(); System.out.print(String.format("%s[%s] ", name, label)); } else if (object instanceof Edge) { Edge edge = (Edge) object; String label = edge.label(); double weight = edge.value("weight"); System.out.print(String.format("---[%s, %.1f]--- ", label, weight)); } } System.out.println("\n"); });
方案二:结构化获取边与关联顶点
使用as和select显式记录每一步的边和顶点,适合需要单独处理边信息的场景:
Vertex start = graph.traversal().V().hasLabel("person").has("name", "marko").next(); graph.traversal().V(start) .repeat(__.outE().as("edge").inV().as("vertex")) .emit() .select("edge", "vertex") .forEachRemaining(map -> { Edge edge = map.get("edge"); Vertex vertex = map.get("vertex"); System.out.println("EDGE: " + edge.label() + " (weight: " + edge.value("weight") + ")"); System.out.println("CONNECTED TO: " + vertex.value("name") + "[" + vertex.label() + "]\n"); });
额外检查点
- 确认SqlG版本为3.1.0,与对应的TinkerPop版本兼容
- 确保事务已正确提交,边数据确实存在于图中
内容的提问来源于stack exchange,提问作者Juvenik
相关产品推荐
相关产品推荐

