Issue Querying with Dynamic Relationship and Node Type

I want to create a generic query that can modify node type and relationship type.
I referenced this link, but it seemed to not work for me.

Here's my code for the query I want:

default void createRelationship(Long idA, Class<?> classA, String relationshipName, Long idB,
                        Class<?> classB) {
                createRelationship(idA, classA.getSimpleName(), relationshipName, idB, classB.getSimpleName());
        }

        @Query("MATCH (idA:$nodeTypeA WHERE ID(idA) = $idA)" +
        "MATCH (idB:Person WHERE ID(idB) = $idB)" +
        "MERGE (idA)-[:$RELATIONSHIP_NAME]->(idB)")
        void createRelationship(
                        @Param("idA") Long idA,
                        @Param("nodeTypeA") String nodeTypeA,
                        @Param("RELATIONSHIP_NAME") String relationshipName,
                        @Param("idB") Long idB,
                        @Param("nodeTypeB") String nodeTypeB);

The error with $:

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.dao.InvalidDataAccessResourceUsageException: Invalid input '$': expected "%", "(" or an identifier (line 1, column 12 (offset: 11))
"MATCH (idA:$nodeTypeA WHERE ID(idA) = $idA)MATCH (idB:Person WHERE ID(idB) = $idB)MERGE (idA)-[:$RELATIONSHIP_NAME]->(idB)"
            ^; Error code 'Neo.ClientError.Statement.SyntaxError'] with root cause

I have used $ before, so I am unsure why it doesn't work.

In SPEL Format:

@Query("MATCH (idA:#{nodeTypeA} WHERE ID(idA) = $idA)" +
        "MATCH (idB:Person WHERE ID(idB) = $idB)" +
        "MERGE (idA)-[:$RELATIONSHIP_NAME]->(idB)")
        void createRelationship(
                        @Param("idA") Long idA,
                        @Param("nodeTypeA") String nodeTypeA,
                        @Param("RELATIONSHIP_NAME") String relationshipName,
                        @Param("idB") Long idB,
                        @Param("nodeTypeB") String nodeTypeB);

I tried using SPEL, and this is error I got:

Request processing failed: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'nodeTypeA' cannot be found on object of type 'java.lang.Object[]' - maybe not public or not valid?

Please let me know what could be the issue.

Thank you!

The first error is due the fact that you can not use a parameter for labels. They must be literal strings.

For your SpEL approach, try what is demonstrated in this example from the documentation

interface BaseClassRepository extends Neo4jRepository<Inheritance.BaseClass, Long> {

    @Query("MATCH (n:`:#{literal(#nodeTypeA)}`) RETURN n")
    List<Inheritance.BaseClass> findByLabel(String label);
}

https://docs.spring.io/spring-data/neo4j/reference/appendix/custom-queries.html

So, if you mimic their example, your match should look like this:

MATCH (idA: `:#{literal(#nodeTypeA)}`  WHERE ID(idA) = $idA)

Thank you for the help, it works.

1 Like