How to delete relationships with properties by passing parameters?

56 views Asked by At

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

2

There are 2 answers

2
Charchit Kapoor On BEST ANSWER

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();
}
1
BendaThierry.com On

You can check the official Neo4J java documentation with many examples. Especially these one :

Map<String,Object> params = new HashMap<>();
params.put( "name", "Johan" );

String query =
"MATCH (n:Person)" + "\n" +
"WHERE n.name = $name" + "\n" +
"RETURN n";

Result result = transaction.execute( query, params );

And make your minimum use case lighter removing any useless code.