1
votes

Say I have a node in the database with label L and multiple random properties A=B, C=D, etc. I want to merge another node in the database also with label L but only has the properties A=B.

With current Cypher, I could just do a simple:

 merge (node:L {A:B}) return node

But since match/merge considers any nodes with those properties count, it will be merged into the first node. Is there any way to get this exact match? I was thinking of doing something like a

merge (node:L {props}) where {props} == {all node's props}

but that functionality to list all the node's props doesn't exist though it's on their top five ideas.

2

2 Answers

2
votes

If you know the properties you want to compare this will do the trick.

MATCH (node:L {a: "a"}) 
WHERE LENGTH(KEYS(node)) = 1 
WITH (CASE COUNT(node) WHEN 0 then [1] END) AS X 
FOREACH (x in X | create (a:L {a:"a"}));

The number on the LENGTH line must be equal to the number of properties you want to compare, at this case, one.

LENGTH(KEYS(node)) = 1 

EDIT 1 - Same query but returning the node

MATCH (node:L {a: "a"}) 
WHERE LENGTH(KEYS(node)) = 1 
WITH (CASE COUNT(node) WHEN 0 then [1] END) AS X 
FOREACH (x in X | create (a:L {a:"a"})) 
with X
MATCH (node:L {a: "a"}) return node;
1
votes

If you know exactly which property names you want to exclude when determining if there are any matches (prior to creating a node), you can do something like the following. In this example, the properties to exclude when determining if there is a match are "C", "D", and "E".

OPTIONAL MATCH (node:L {A: "B"})
WHERE NOT (has(node.C) OR has(node.D) OR has(node.E))
WITH (CASE WHEN node IS NULL THEN [1] ELSE [] END) AS cn
FOREACH (x IN cn | CREATE (:L {A: "B"}))
RETURN cn[0];

The returned value will be 1 if the node was created, or null if it was not.