Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating unique structures in Neo4j with them having nodes that are part of another structure

Let's say that we have n nodes with label :Test and a unique property called type.

UNWIND[{ type:"a" }, { type:"b" }, { type:"c" }, { type:"d" }] AS x
MERGE (t:Test { type: x.type })
RETURN t

That looks like this

Base structure

Now let's introduce a node of label :Collection. The purpose if this node is to have a unique relationship pattern with the :Test nodes.

MATCH (a:Test { type:"a" }),(b:Test { type:"b" })
CREATE UNIQUE (x:Collection)-[:HAS]->(a),(x:Collection)-[:HAS]->(b)
Return *

1st collection

The problem that I face starts occurring when I try to make another unique structure, like the previous one, but with some nodes in common.

MATCH (a:Test { type:"a" })
CREATE UNIQUE (x:Collection)-[:HAS]->(a)
RETURN *

The expected result is that another node of label :Collection gets created and linked to :Test {type:"a"} but the actual result is that it matches the previous data structure and returns that instead of creating a new one.

2nd collection

The expected result should have 2 :Collection nodes, one linked to type:"a", the other one linked to type:"a" and type:"b".

expected result

Any input kind of input will be very appreciated :D

like image 396
Ștefan-Gabriel Muscalu Avatar asked Oct 31 '22 01:10

Ștefan-Gabriel Muscalu


1 Answers

From the neo4j docs on CREATE UNIQUE:

CREATE UNIQUE is in the middle of MATCH and CREATE — it will match what it can, and create what is missing. CREATE UNIQUE will always make the least change possible to the graph — if it can use parts of the existing graph, it will.

You add Collection nodes without any properties. I think if CREATE UNIQUE finds a Collection node, it will use it. This is how CREATE UNIQUE is supposed to work.

So if you want a new Collection that is linked to some Test nodes, you can either add some unique properties to the node:

MATCH (a:Test { type:"a" })
CREATE UNIQUE (x:Collection {key: 'unique value'})-[:HAS]->(a)
RETURN *

Or create it in a separate step:

MATCH (a:Test { type:"a" })
CREATE (x:Collection)
CREATE (x)-[:HAS]->(a)
RETURN *

Or use MERGE instead of CREATE UNIQUE.

like image 136
Martin Preusse Avatar answered Jan 04 '23 14:01

Martin Preusse