Stefan
Stefan

Reputation: 448

Execute query on neo4j database from Java, parsing the result

I access the neo4j database via GraphDatabaseService. I added some nodes and relation and want to do a query. My goal is to get all Nodes that got an Calling relation to the endnode. So i have the whole paths to this node. (e.g.: node1 -calling-> node2 -calling*-> nodeX -calling-> endnode)

I tried something like this:

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;
}

Problem for me is, that the result is a Map<'String, Object>, and i want do get the id's or names of the nodes that are in the relation. I tried to cast the Object to PathImpl because thats the type that is returned (figured out by debug), but it seams like that this class is in a different class loader so the statement instanceof returns false. v.toString() returns a String representation of the liked nodes with id's (e.g.: p : (24929)--[CALLING,108061]-->(24930))

My question is, can i access this information in a better way or how can i change the classLoader (if that is the problem, i'm working with eclipse in a gradle project) to make that cast happened. I don't wanna parse the String to get the id's and get the nodes from the db via that property, its seams ugly for me.

Upvotes: 2

Views: 940

Answers (2)

cybersam
cybersam

Reputation: 66989

If you want to get the names of the start and end nodes, then you should modify the Cypher code to return them (instead of the paths), which would greatly simplify the code needed to extract that data from the response. For example:

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

Upvotes: 1

Stefan
Stefan

Reputation: 448

After trying cybersam's valid answer to change the cypher query, i discovered another way without changing that query, that suits my goal better. For me the goal was to get the whole path not only the name/id of the linked nodes. That information is exactly how i want in the parameter 'p' (see Query) but i could not cast that type. The reason for that was that Neo4j is using a internal implementation of PathImpl. To make my solution in the Question work, i have to use Path instead of PathImpl so i dont have to import the intern Type. So i changed the imports from:

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

to

import org.neo4j.graphdb.Path;

and test for Path instead of PathImpl.

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

Now i can access the whole path. Hope that will help other people too.

Upvotes: 0

Related Questions