Benjamin McFerren
Benjamin McFerren

Reputation: 862

CYPHER store order of node relationships of the same label when I create

I have multiple relationships that stem from a node. Each of these relationships are of the same label. The relationships point to a child node (not neccesarily unique). After I fetch all child nodes that link to the parent by this relationship label, I order them by a relationship property called trueindex. I then have an array of nodes that my client can iterate through in the correct sort order.

The problem comes when I try to "push, pop, unshift, etc..." onto this array. If I want to add a new relationship to the front of the order, I have to create a new relationship, use it to link the parent to the child node, then add a 0 value to the relationships trueindex property. The problem is that there already is a relationship with a trueindex value of zero and I need to perform somesort of casecading function that increments the trueindex of all other relationships (of the same type that all stem from that same parent node). I am trying to find a way to get this "array-like" index number functionality for free

The only way I can think to do so is to first delete all relationships of that particular label that stem from the parent. And then rewrite the entire array (with all the prexisting relationship that increment their trueindex by one) in order to reflect the correct order. This is fine for small cases but if I plan for a parent node to have a significant amount of relationships, then its a problem to rewrite the entire array (set of relationships) every time I want to add, remove by index, pop, etc and yet still maintain an order of relationships that stem from the parent node.

Does Neo4j have some sort of relationship feature to write to the correct order when creating new relationships?

I am very grateful for advise you can offer.

Upvotes: 2

Views: 931

Answers (2)

s.d
s.d

Reputation: 29436

You can use SET to increment or decrement properties of existing relations first.

The following example shifts trueIndex of existing relations and pushes a new relation (to an existing child node) at index 0:

MATCH (n:Root)-[r:HAS]->(c:Child) 
WHERE id(n) = 0 
SET r.trueIndex = r.trueIndex + 1
WITH n, min(r.trueIndex) as indexStart, max(r.trueIndex) as indexEnd
CREATE (n)-[r:HAS  {trueIndex:(indexStart-1)}]->(c:Child)
WHERE id(c) = 12
RETURN n,r,c

You can modify the query according to your needs.

Design wise, I agree with @jjaderberg 's answer, it would be simpler to keep a linked list to represent an array.

Upvotes: 1

jjaderberg
jjaderberg

Reputation: 9952

Try keeping the child nodes in linked lists. The structure will look something like

(p:Parent)-[r1:CHILDREN]->(c1:Child)-[r2:NEXT]->(c2:Child)-[r3:NEXT]->(c3:Child)

This maintains the order of your child nodes and allows you to improve your interaction with the structure in two ways:

  1. Inserting a new node into this structure only involves changes to the relationships 'before' and 'after' the place that node is going, as opposed to the entire structure. For example, to insert newc between c1 and c2, you delete r2, create newc and create :NEXT relationships from c1 to newc to c2. Analogous for other operations: all your alterations are now local within the structure.

  2. You use relationships and their types to structure your data, instead of relationship properties. This is more flexible and almost always more performant (sometimes much more performant).

To read a single child from this structure you now use your trueindex to declare the depth in the linked list at which to find the node, i.e.

MATCH (parent:Parent {parentId: 1234})-[:CHILDREN]->()-[:NEXT*3]->(child)
RETURN child

and to retrieve a parent with all its children

MATCH (parent:Parent {parentId: 1234})-[:CHILDREN|NEXT*]->(child)
RETURN parent, COLLECT(child) as children

Upvotes: 2

Related Questions