Search code examples
javaneo4jneo4j-java-api

How to delete relationships with properties by passing parameters?


env:

  1. Neo4j-4.4.x
  2. neo4j-jdbc-driver 4.0.9

Image that I execute the following cypher to get a ‘teacher’ node and a ‘student’ node, the relationship between them is ‘educate’, and the relationship has a year attribute.

cypher:

merge (subject:Teacher{teacher_id: 'teacher_001'})  
merge (object:Student{student_id:'student_001'})  
merge (subject)-[relation:educate]->(object) set relation.year='3'  return subject,relation,object

figure-1:
enter image description here

Why does my following approach with the help of parameters maps not work?

@Test
public void testDeleteEdgeWithProperties_001() {
    Driver driver = GraphDatabase.driver("neo4j://localhost:7687", AuthTokens.basic("neo4j", "neo4j123"));
    Session session = driver.session();
    Transaction transaction = session.beginTransaction();

    String relationModelType = "educate";
    String subjectModelType = "Teacher";
    String subjectKey = "teacher_id";
    String subjectId = "teacher_001";
    String objectModelType = "Student";
    String objectKey ="student_id";
    String objectId = "student_001";

    Map<String, Object> properties = new HashMap<>();
    properties.put("year","3");
    Map<String, Object> params = new HashMap<>();
    params.put("relation_prop", properties == null ? new HashMap<>() : properties);

    // 删除
    String conditionDeleteCypher = " WHERE relation = $relation_prop";
    String cypher =  " MATCH (subject:" + subjectModelType + "{" + subjectKey + ": '" + subjectId + "'}) " +
            " MATCH (object:" + objectModelType + "{" + objectKey + ":'" + objectId + "'}) " +
            " MATCH (subject)-[relation:" + relationModelType +"]->(object) " +
            conditionDeleteCypher +
            " DELETE relation";

    System.out.println(cypher);
    transaction.run(cypher, params);
    transaction.commit();
    transaction.close();
}

The cypher printed by the above method is as follows:

MATCH (subject:Teacher{teacher_id: 'teacher_001'})  MATCH (object:Student{student_id:'student_001'})  MATCH (subject)-[relation:educate]->(object)  WHERE relation = $relation_prop DELETE relation

However, the above cypher can be executed successfully in the neo4j browser (see figure-2 below). What's wrong with me? Appreciate any helpful responses

figure-2:
enter image description here

I tried several ways to set the parameter, but none of them worked.

String conditionDeleteCypher = " WHERE relation = $relation_prop";
String conditionDeleteCypher = " WHERE relation =+ $relation_prop";
String conditionDeleteCypher = " WHERE relation += $relation_prop";

The @Test code I provided is completely executable, no error message. After execution, the neo4j browser can still find the target relationship, indicating that the method was executed but did not take effect.

enter image description here


Solution

  • The query generated by your code, is logically incorrect:

    MATCH (subject:Teacher{teacher_id: 'teacher_001'})  
    MATCH (object:Student{student_id:'student_001'})  
    MATCH (subject)-[relation:educate]->(object)  WHERE relation = $relation_prop 
    DELETE relation
    

    In this query, you are comparing the whole Neo4j Relationship object, to a query object, which is like this:

    {
      relation_prop: {
         year: "3"
      }
    }
    

    This won't work because of two reasons:

    1. relation_prop is not a valid relation property.
    2. There are a lot of other internal properties, part of a relationship.

    In the query you ran on Neo4j Browser, you are only checking the value of the year property. To fix it you can try this:

    @Test
    public void testDeleteEdgeWithProperties_001() {
        Driver driver = GraphDatabase.driver("neo4j://localhost:7687", AuthTokens.basic("neo4j", "neo4j123"));
        Session session = driver.session();
        Transaction transaction = session.beginTransaction();
    
        String relationModelType = "educate";
        String subjectModelType = "Teacher";
        String subjectKey = "teacher_id";
        String subjectId = "teacher_001";
        String objectModelType = "Student";
        String objectKey ="student_id";
        String objectId = "student_001";
    
        Map<String, Object> properties = new HashMap<>();
        properties.put("year","3");
    
        // 删除
        String conditionDeleteCypher = " WHERE relation.year = $year";
        String cypher =  " MATCH (subject:" + subjectModelType + "{" + subjectKey + ": '" + subjectId + "'}) " +
                " MATCH (object:" + objectModelType + "{" + objectKey + ":'" + objectId + "'}) " +
                " MATCH (subject)-[relation:" + relationModelType +"]->(object) " +
                conditionDeleteCypher +
                " DELETE relation";
    
        System.out.println(cypher);
        transaction.run(cypher, properties);
        transaction.commit();
        transaction.close();
    }