Home > Software design >  Spring Data Neo4j pass relationship name as parameter
Spring Data Neo4j pass relationship name as parameter

Time:08-30

Is it possible to pass relationship name as parameter?

I'm trying to do this with SpEL:

@Query("MATCH (l:Location:Requirable {id: $locationId})<-[rld::#{#relationshipName}]-(d:Decision {id: $decisionId}) "  
        "DETACH DELETE rld")
void detachLocation(@Param("locationId") Long locationId, @Param("decisionId") Long decisionId, @Param("relationshipName") String relationshipName);

but it fails with the following error:

org.springframework.dao.InvalidDataAccessResourceUsageException: Cypher execution failed with code 'Neo.ClientError.Statement.SyntaxError': Invalid input '$': expected an identifier (line 1, column 52 (offset: 51))
"MATCH (l:Location:Requirable {id: $locationId})<-[:$spel_expr0]-(d:Decision {id: $decisionId}) OPTIONAL MATCH (l)-[rdt:CONTAINS]->(t:Translation:Requirable) WHERE ($iso6391 IS NOT null AND t.iso6391 = $iso6391) RETURN l, rdt, t"
                                                    ^.; nested exception is org.neo4j.ogm.exception.CypherException: Cypher execution failed with code 'Neo.ClientError.Statement.SyntaxError': Invalid input '$': expected an identifier (line 1, column 52 (offset: 51))

I user Spring Data Neo4j 5.3.9.RELEASE OGM version

is it possible or no? If so, could you please show how.

CodePudding user response:

It's not exactly what you were looking for, but I would consider simple WHERE condition (if you're not working on really huge datasets and you're not really care about few more db hits).

WHERE type(r) = $relationshipName

Here query which should work:

@Query("MATCH (l:Location:Requirable {id: $locationId})<-[rld]-(d:Decision {id: $decisionId}) WHERE type(rld) = $relationshipName DETACH DELETE rld")
void detachLocation(@Param("locationId") Long locationId, @Param("decisionId") Long decisionId, @Param("relationshipName") String relationshipName);

CodePudding user response:

The answer is no. Relationship types and Node Labels cannot be parameterized in Cypher as of now. Either you can go with @degath answer. Or construct the query using strings, something like this:

public static final String query = "MATCH (l:Location:Requirable {id: $locationId})<-[rld:REL_TYPE]-(d:Decision {id: $decisionId}) DETACH DELETE rld"

String finalQuery = query.replaceAll("REL_TYPE", relationshipName);

Then you can pass this generated query to an APOC function. Something like this:

@Query("CALL apoc.cypher.run($query, {locationId: $locationId, decisionId: $decisionId}) yield value")
void detachLocation(@Param("locationId") Long locationId, @Param("decisionId") Long decisionId, @Param("query") String query);

Note this is not tested.

  • Related