2017-06-08 63 views
1

我通过GraphDatabaseService访问neo4j数据库。我添加了一些节点和关系,并希望进行查询。我的目标是让所有与呼叫终端有呼叫关系的节点。所以我有整个路径到这个节点。 (例如:节点1 -calling->节点2 -calling * - >节点X -calling->终端节点)从Java执行对neo4j数据库的查询,解析结果

我想是这样的:

GraphDatabaseService _graphDatabase; // db is running and working fine 
Node node;//given by the function call 

HashMap<String, Object> properties = Maps.newHashMap(); 
properties.put("name", getPropertyFromNode(node, "name")); 
String query = "MATCH p=(startnode)-[rel:CALLING*]->(endnode) WHERE endnode.name = {name} RETURN p"; 

Result result = _graphDatabase.execute(query, properties); 
while (result.hasNext()) { 
    Map<String, Object> next = result.next(); 
    next.forEach((k, v) -> { 
     System.out.println(k + " : " + v.toString()); 
     if (v instanceof PathImpl) { 
      PathImpl pathImpl = (PathImpl) v; 
      String startNodeName = getPropertyFromNode(pathImpl.startNode(), "name"); 
      String endNodeName = getPropertyFromNode(pathImpl.endNode(), "name"); 
      System.out.println(startNodeName + " -calling-> " + endNodeName); 
     } 
    }); 
} 

public String getPropertyFromNode(Node node, String propertyName) { 
    String result = null; 
    try (Transaction transaction = _graphDatabase.beginTx()) { 
     result =node.getProperty(propertyName).toString(); 
     transaction.success(); 
    } 
    return result; 
} 

问题对我来说,这个结果是一个地图< '字符串,对象>,并且我想要得到id或关系中的节点的名称。我试图将对象转换为PathImpl,因为那是返回的类型(通过调试计算出来),但它像接口那样处于不同的类加载器中,因此语句instanceof返回false。 (24929) - [CALLING,108061] - >(24930))

我的问题是,我可以访问这个以更好的方式获得信息,或者如何改变classLoader(如果这是问题,我正在gradle项目中使用eclipse)来发生这样的事情。 我不想解析字符串来获取ID的,并通过该属性从数据库中获取节点,它的接缝对我来说很丑。

回答

0

试图cybersam的有效回答改变暗号查询后,我发现另一种方式在不改变该查询,适合我的目标更好。 对于我来说,目标是获得整个路径,不仅是链接节点的名称/ ID。该信息正是我想要的参数'p'(请参阅查询),但我不能投这种类型。 原因是Neo4j正在使用PathImpl的内部实现。 为了让我的解决方案在问题工作中,我必须使用Path而不是PathImpl,所以我不必导入实习生类型。所以我改变了进口:

import org.neo4j.graphalgo.impl.util.PathImpl; 

import org.neo4j.graphdb.Path; 

和测试路径,而不是PathImpl。

if (v instanceof Path) { 
    Path path = (Path) v; 
    Iterable<Node> nodes = path.nodes(); 
    nodes.forEach(n -> System.out.println(n.toString())); 
} 

现在我可以访问整个路径。希望这也能帮助其他人。

1

如果您想获取开始和结束节点的名称,那么您应该修改Cypher代码以返回它们(而不是路径),这将极大地简化从响应中提取数据所需的代码。例如:

MATCH p=(startnode)-[rel:CALLING*]->(endnode) 
WHERE endnode.name = {name} 
RETURN startnode.name AS s_name, endnode.name AS e_name, p; 
+0

看起来像我深入到用java解决这个问题,而不是思考两次有关密码查询,thx – Stefan

+0

问题这种方式是即时通讯丢失关于节点之间的关系的信息...所以我得到了所有的列表节点是的,但我不知道路径如何看起来像 – Stefan

+0

为了获得路径,你只需要在'RETURN'子句中包含路径'p'。我已经更新了我的答案。 – cybersam