I have a bunch of relationships where I would like to create a friendly id for the child objects so that I can have friendlier URLs.
Every time I create a child object for a particular parent object I would like to automatically include a friendly id which increments sequentially. So the first child would have friendly id 1, the second would have friendly id 2, etc. I don't want to reuse id's if children are deleted. To complicate matters, there are many such relationships that I would like to do this for.
Currently I'm caching some state on the parent node and using that to populate the friendly id when creating children:
CREATE (o:Foo {name: 'parent', nextChildId: 1})
MATCH (o:Foo)
WHERE o.name = 'parent'
CREATE (o)-[:HAS]->(c:Child {name: 'child1', friendlyId: o.nextChildId})
SET o.nextChildId = o.nextChildId + 1
MATCH (o:Foo)
WHERE o.name = 'parent'
CREATE (o)-[:HAS]->(c:Child {name: 'child2', friendlyId: o.nextChildId})
SET o.nextChildId = o.nextChildId + 1
The problem is that there is a chance that two children will end up with the same friendly id since two clients could try and create children at the same time. I'm not sure how to prevent this from happening.
Neo4j is fully ACID compliant. You can run this in a transaction with
SERIALIZABLE
isolation level and acquiring the lock on the node of interest. Remember however that this might be degrade the performance.For anyone else that is looking to do this, I got a workaround from the Neo4j Google group. The trick is to create a lock on the node by removing a non-existent property. This serializes access to the node and prevents multiple children from getting the same id.