3
votes

I'm looking for a way to generate unique identifiers for all my nodes/relationships in Neo4j, based on an incrementing counter (not big long uuids).

The internal ids maintained by the Neo4j engine are known not to be reliable as outside references.

A solution that comes close is the code proposed in this question, but it doesn't work when a single CREATE clause creates multiple new nodes:

// get unique id
MERGE (id:UniqueId{name:'Person'})
ON CREATE SET id.count = 1
ON MATCH SET id.count = id.count + 1
WITH id.count AS uid
// create a new node attached to every existing :something node
MATCH (n:something)
CREATE (:somethingRelated {id:uid}) -[:rel]-> (n)

When there are multiple (n:something), every newly created (:somethingRelated) will share the same id. Is there some way around this, using only Cypher?

2
You can just set the internal node-id as your external id. SET n.id = id(n) which is an incrementing number. But which can be reused after deleting and recreating nodes.Michael Hunger
@MichaelHunger: Which makes it useless, unfortunately. :-(mhelvens
Not really if you take care to not to keep those id's used elsewhere after the original node is deleted all is fine.Michael Hunger
For your code, you can allocate a block of id's.Michael Hunger
It's an outside requirement for us that ids are never re-used.mhelvens

2 Answers

2
votes

Try this to allocate a block of ids:

// collect nodes to connect
MATCH (n:Crew) WITH collect(n) AS nodes
MERGE (id:UniqueId { name:'Person' })
// reserve id-range
SET id.count = coalesce(id.count,0)+ size(nodes)
WITH nodes, id.count - size(nodes) AS base 
// for each index
UNWIND range(0,size(nodes)-1) AS idx
// get node, compute id
WITH nodes[idx] AS n, base +idx AS id
CREATE (:SomethingRelated { uid:id })-[:rel]->(n)
1
votes

From my point of view it's not possible to do that in Cypher.

I suggest you to write Java Extension for that, because your approach with Cypher would not work in concurrent environment. You are not able to secure uniqueness.

Could you please tell us more about your use case and why you don't to use UUID? - https://github.com/graphaware/neo4j-uuid

Based on your comment below I suggest to create ID's in your application.