18

As far as I understand it the IDs given by Neo4j (ID(node)) are unstable and behave somewhat like row numbers in SQL. Since IDs are mostly used for relations in SQL and these are easily modeled in Neo4j, there doesn't seem to be much use for IDs, but then how do you solve retrieval of specific nodes? Having a REST API which is supposed to have unique routes for each node (e.g. /api/concept/23) seems like a pretty standard case for web applications. But despite it being so fundamental, the only viable way I found were either via

  • language specific frameworks
  • as an unconnected node which maintains the increments:
// 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 Person node
CREATE (p:Person{id:uid,firstName:'Gabriel',lastName:'Smith'})
RETURN p AS person

Source: http://www.neo4j.org/graphgist?8012859

Is there really not a simpler way and if not, is there a particular reason for it? Is my approach an anti-pattern in the context of Neo4j?

Gregor Weber
  • 690
  • 9
  • 24

2 Answers2

7

Neo4j internal ids are a bit more stable than sql row id's as they will never change during a transaction for e.g.

And indeed exposing them for external usage is not recommended. I know there are some intentions at Neo internals to implement such a feature.

Basically people tend to use two solutions for this :

  1. Using a UUID generator at the application level like for PHP : https://packagist.org/packages/rhumsaa/uuid and add a label/uuid unique constraint on all nodes.

  2. Using a very handful Neo4j plugin like https://github.com/graphaware/neo4j-uuid that will add uuid properties on the fly, so it remove you the burden to handle it at the application level and it is easier to manage the persistence state of your node objects

Christophe Willemsen
  • 19,399
  • 2
  • 29
  • 36
  • 7
    This does not answer the question. Auto increment id's can be used to sort objects in order of creation, which cannot be done with uuid's – Pavel Niedoba Aug 29 '16 at 10:34
  • I believe adding a unix timestamp or some kind of date-time prefix to the random unique string would fix the sorting problem. – Guy Oct 01 '17 at 18:17
  • @PavelNiedoba why dont you sort by maybe adding a property with a timestamp of when added and go with the uuid option? – nonybrighto Feb 18 '18 at 07:14
  • Timestamps in java have miliseconds resolutions, depends on time setting and this solution adds serious data overkill, when this could be done with single INT and Neodb.getCounter("my-numbering").next() – Pavel Niedoba Sep 04 '18 at 16:08
  • UUID version 1, which is timestamp-based, has the advantage of being sortable too. – Colyn Brown Jan 26 '20 at 06:13
1

I agree with Pavel Niedoba.

I came up with this without and UniqueID Node:

MATCH (a:Person)
WITH a ORDER BY a.id DESC LIMIT 1
CREATE (n:Person {id: a.id+1})
RETURN n

It requires a first Node with an id field though.

mobin
  • 318
  • 2
  • 6
  • This doesn't insure data consistency since you can have a creation at same time, you should add "unique constraints" to handle this case, https://neo4j.com/docs/cypher-manual/current/constraints/examples/ – Lounis Jan 14 '22 at 17:24