1
votes

I am using Neo4j (version 3.4.1) and Spring-data-neo4j (5.0.10.RELEASE) in my application. I am also using OGM.

I have the below relationship between my nodes:

enter image description here

A vehicle (V) has Part(s) (P1 and P2). Parts can be bought from dealers (D1, D2 and D3). Part themselves can be linked to each other (for e.g P2 is linked with P1)

I am trying to write a cypher query to get a Part node matching an id. I want to get the node along with its related nodes and relationships.

Below is my query:

@Query(("MATCH (Vehicle:v{id:{vehicleId}}) \n" +
            "MATCH (Part:part{id:{id}}) \n" +
            "WITH DISTINCT part \n" +
            "MATCH q=(v)-[:HAS_PART]->(part)-[:FROM_DEALER|:IS_LINKED_WITH]->()\n" +
            "RETURN nodes(q), relationships(q)"))
    Optional<Part> findByIdForGivenPart(@Param("vehicleId") String vehicleId, @Param("id") String id);

When I run the query passing id of Part P1, I get the correct result. However, when I run it passing id of Part P2, I get an exception :

org.springframework.dao.IncorrectResultSizeDataAccessException: Incorrect result size: expected at most 1   

which I understand is because in this case two parts are getting returned.

I would like to know the cypher query syntax so that I get correct result (i.e P2) along with its related nodes when I pass id of P2. I want that the P1 node should also be returned as P2 is linked with P1.

Any help would be highly appreciated.

Edit: Added queries to generate sample data.

merge (v:Vehicle{id:'V1'})-[:HAS_PART]->(p:Part{id:'P1'})-[:FROM_DEALER]->(d1:Dealer{id:'D1'})

match(p:Part{id:'P1'})
merge (p)-[:FROM_DEALER]->(d2:Dealer{id:'D2'})

match (v :Vehicle{id:'V1'})
match (d2:Dealer{id:'D2'})
merge (v)-[:HAS_PART]->(p:Part{id:'P2'})-[:FROM_DEALER]->(d2)

match(p2:Part{id:'P2'})
match(p1:Part{id:'P1'})
merge (p2)-[:FROM_DEALER]->(d3:Dealer{id:'D3'})
merge (p2)-[:IS_LINKED_WITH]->(p1)

Regards, V

1
please share the sample data for P2 having the same id but 2 different nodes. Show use the relationships in your example. Thanks.jose_bacoy
P1 and P2 are two nodes of type Part. P1 and P2 are their ids. If that makes sense. Same is the case with D1, D2 etc. Nodes of type DealerLearnToLive

1 Answers

1
votes

I see three problems here:

The first is that you're using a directed relationship in your 3rd MATCH clause from part to the unnamed node at the end:

MATCH q=(v)-[:HAS_PART]->(part)-[:FROM_DEALER|:IS_LINKED_WITH]->()

This means that when you query for P1, it does not match with P2, so the only : return P1

The second problem is that your query doesn't quite match your method, which is declared to return Optional<Part> while your query wants to return all the nodes (and relationships) along that same path q. Also the name of the method (findByIdForGivenPart) is not quite expressing what you want to accomplish with it.

The third problem is that your first two MATCH clauses seem to have the alias name and specified labels switched in the syntax:

MATCH (Vehicle:v{id:{vehicleId}})
MATCH (Part:part{id:{id}})

I believe these should be:

MATCH (v:Vehicle {id:{vehicleId}})
MATCH (part:Part {id:{id}})

which also leads me to believe that you may have some test data in your graph with nodes that have labels such as v and part (instead of Vehicle and Part) possibly from earlier MERGE statements that were intended to set up test data.