How to display a tree structure in Neo4j?

I am working on a description of a tree dataset in Neo4j. In my current model, a node can have n links to other nodes, making them children of the node of these nodes:

root | \-- A | \-- 1 | \-- 2 
  • Root Links
  • 1 and 2 link to A
  • root is the parent of A
  • 1 and 2 are children of A

Since I use nodejs (with node-neo4j ), reading the database is limited to using Cypher. To read the nodes, I use the following query:

 START n=node(1) -- this is the root node MATCH (n)<-[linkedby:links*]-x, x-[linksto?:links*1]->() -- get all nodes that link to the root node and all nodes linking to those nodes, etc, etc and retrieve all nodes those found nodes link to RETURN n, x, linkedby, LAST(linkedby) AS parent, COLLECT(DISTINCT linksto) AS links -- the last in the path of linkedby is the direct parent ORDER BY length(linkedby), parent.rank? -- ordering so that parents are fetched before their children from the result set 

My problem: this query becomes very slow (> 1 s) as the number of nodes and relationships increases.

Is there a better way to model nodes and relationships? Do I need different relationships between parent nodes and child nodes? Or should I somehow modify the request?

Thanks for any pointers!


1) The problem of the real world: This is a business process tool in which services are associated with processes, organizations, teams, etc., to provide information on what services are required, when and by whom, and also to provide information that will provide this service or is responsible.

So for example:

Service S is used in processes P1 and P2:

 P1 P2 | | \---+-- S 

Service S is controlled by the T command:

 T | \-- S 

Team T is part of O:

 O | \-- T 

Wood:

 root | | +-- Processes | | | +-- P1 | | | | | \-- S | | | \-- P2 | | | | | \-- S | +-- Organisations | | | +-- O | | | \-- T | | | \-- S 

2) My data in console.neo4j.org :

 CREATE (r {name:'root'}), (ps {name: 'Processes'})-[:links]->r, (p1 {name: 'P1'})-[:links]->ps, (p2 {name: 'P2'})-[:links]->ps, (s {name: 'Service'})-[:links]->p1, s-[:links]->p2, (org {name: 'Organisations' })-[:links]->r, (t {name: 'Team'})-[:links]->org, s-[:links]->t 
+6
source share
1 answer

So, the other day I talked with Michael Hunger , and he admitted that Cypher is not very good (yet) in processing recursive queries. This should change in 2.1, but before that, he suggested writing an unmanaged extension , which I could then call from nodejs.

This completely solved my problem: extracting a tree using simple Java is about 10 times faster than using Cypher.

Simplified code:

 public class EntitiesStream { public Entity load(long nodeId) { Node n = database.getNodeById(nodeId); Entity entity = Entity.from(n); loadChildren(n, entity); return entity; } private void loadChildren(Node n, Entity e) { for (Relationship linksFrom: n.getRelationships(Direction.INCOMING, Relationships.links)) { Node startNode = linksFrom.getStartNode(); Entity childEntity = Entity.from(startNode); e.addChild(((Number) linksFrom.getProperty("rank")).longValue, childEntity); this.loadChildren(startNode, childEntity); } } } public class Entity { private final TreeMap<Long, Entity> sortedChildren; Entity(long dbId) { this.sortedChildren = new TreeMap<>(); // ... } public static Entity from(Node node) { Entity e = new Entity(node.getId()); // ... return e; } public void addChild(Long rank, Entity childEntity) { sortedChildren.put(rank, childEntity); } } 
+1
source

Source: https://habr.com/ru/post/954050/


All Articles