Search code examples
neo4jcypherlibneo4j-client

Neo4j MERGE creates duplicates in code but not in console


I am using the MATCH and MERGE operation in Neo4j in order to avoid duplicate relationships. My program does the following: whenever two nodes are "close", it creates a relationship from node A to B and vice-versa. I only want one of those relations, and it is hard to control this in the program so I am using the database instead.

Imagine that nodes 3 and 81 are related to each other. If I run

OPTIONAL MATCH (n:Node {id:3}), (m:Node {id:81})
MERGE (n)-[r:REL {relT: "SOR" , simT:2205}]->(m)

twice from the console, the second query doesn't do anything, which is the expected behavior. However, when I use neo4j-client to log these relations (it sends the query twice, as explained), two relations are created. I think that this has nothing to do with the client I am using, as the MERGE is obviously interpreted by neo4j. I have checked if relationship properties created are equal or not, but they seem to be the same (first and last row in the table):

output

Anyone can give me any hint on how to troubleshoot this?

EDIT: The code I am using in my C code is:

  std::vector<neo4j_map_entry_t> vParams =
    { node1Id, node2Id, relT, simT };

  neo4j_result_stream_t *results =
      neo4j_run (
      connection,
      "OPTIONAL MATCH (n:Node {id: {node1Id}}), (m:Node {id: {node2Id}}) MERGE (n)-[r:REL {relT: {relT}, simT: {simT}}]->(m)",
      neo4j_map (vParams.data (), vParams.size ()));

which makes me wonder a couple of things... Am I sending a prepared statement? Does MERGE work with prepared statements? As far as I can tell, I am not sending any prepared statement, I am just binding the variables and sending the whole query.


Solution

  • I am not sure if this is the cause of your issue, but if you want to ensure that there is only one instance of a relationship (regardless of the directionality) between 2 nodes, your MERGE clause should specify a directionless relationship pattern.

    For example:

    OPTIONAL MATCH (n:Node {id:3}), (m:Node {id:81})
    MERGE (n)-[r:REL {relT: "SOR" , simT:2205}]-(m);
    

    Notice that the pattern does not specify a relationship direction. This causes the MERGE to check for an existing relationship in either direction (instead of in a single direction).