I'm using Memgraph (but open to using Neo4j) and need some help on building a recursive query to build out a tree. I'm new to Cypher so my attempts so far haven't been successful. I've played around with the CALL subqueries but can't seem to get the format and ordering right.
My goals are:
- Be able to fetch a Node, and its direct edges - but the edges should be limited to a certain number sorted by a edge property value. E.g. Get Node A and 3 of its edges ordered by property X.
- Be able to fetch a Node, and based on some variable be able to specify the depth to "walk" to tree. E.g. Get Node A, and for each of its 3 edges (sorted by X), get those edge's edges the using the same filter function, up to the depth limit. Bonus points if it can filter out the parent node so it's only a directed tree.
Some concrete examples - given the following graph. Note this is not real data and I'm aware the "age" property is not symmetrical between Nodes. Just threw it together for the question.
CREATE (n0:Node {name: "a"}) CREATE (n1:Node {name: "b"}) CREATE (n2:Node {name: "c"}) CREATE (n3:Node {name: "d"}) CREATE (n4:Node {name: "e"}) CREATE (n5:Node {name: "f"}) CREATE (n6:Node {name: "g"}) CREATE (n7:Node {name: "h"}) CREATE (n8:Node {name: "i"}) CREATE (n9:Node {name: "j"});
CREATE (n0)-[:KNOWN_FOR {age: 20} ]->(n2) CREATE (n0)-[:KNOWN_FOR {age: 7} ]->(n1) CREATE (n0)-[:KNOWN_FOR {age: 15} ]->(n4) CREATE (n0)-[:KNOWN_FOR {age: 23} ]->(n3) CREATE (n0)-[:KNOWN_FOR {age: 5} ]->(n7) CREATE (n1)-[:KNOWN_FOR {age: 10} ]->(n6) CREATE (n1)-[:KNOWN_FOR {age: 14} ]->(n2) CREATE (n1)-[:KNOWN_FOR {age: 24} ]->(n3) CREATE (n1)-[:KNOWN_FOR {age: 19} ]->(n5) CREATE (n2)-[:KNOWN_FOR {age: 24} ]->(n8) CREATE (n2)-[:KNOWN_FOR {age: 25} ]->(n3) CREATE (n2)-[:KNOWN_FOR {age: 17} ]->(n1) CREATE (n3)-[:KNOWN_FOR {age: 7} ]->(n4) CREATE (n3)-[:KNOWN_FOR {age: 10} ]->(n7) CREATE (n3)-[:KNOWN_FOR {age: 25} ]->(n6) CREATE (n3)-[:KNOWN_FOR {age: 22} ]->(n1)CREATE (n4)-[:KNOWN_FOR {age: 21} ]->(n0) CREATE (n4)-[:KNOWN_FOR {age: 24} ]->(n6) CREATE (n4)-[:KNOWN_FOR {age: 17} ]->(n8) CREATE (n5)-[:KNOWN_FOR {age: 14} ]->(n9) CREATE (n5)-[:KNOWN_FOR {age: 8} ]->(n0) CREATE (n5)-[:KNOWN_FOR {age: 15} ]->(n8) CREATE (n5)-[:KNOWN_FOR {age: 18} ]->(n6) CREATE (n5)-[:KNOWN_FOR {age: 22} ]->(n4) CREATE (n6)-[:KNOWN_FOR {age: 7} ]->(n4) CREATE (n6)-[:KNOWN_FOR {age: 21} ]->(n2) CREATE (n7)-[:KNOWN_FOR {age: 25} ]->(n3) CREATE (n8)-[:KNOWN_FOR {age: 18} ]->(n7) CREATE (n8)-[:KNOWN_FOR {age: 12} ]->(n3) CREATE (n9)-[:KNOWN_FOR {age: 14} ]->(n4) CREATE (n9)-[:KNOWN_FOR {age: 15} ]->(n3) CREATE (n9)-[:KNOWN_FOR {age: 7} ]->(n2) CREATE (n9)-[:KNOWN_FOR {age: 14} ]->(n8);
Examples
Get Node A and 3 of its children ordered by KNOWN_FOR age desc, where age > 5. Should return:
A ->
- D (age: 23)
- C (age: 20)
- E (age: 15)
Get Node A, and its children to a depth of 3, where its children have a limit of 2 order by age desc. Should return:
A
-> D (age: 23)
-> G (age: 25)
-> C (age: 21)
-> E (age: 7)
-> B (age: 22)
-> D (age: 24)
-> F (age: 19)
-> C (age: 20)
-> D (age: 25)
-> G (age: 25)
-> B (age: 22)
-> I (age: 24)
-> H (age: 18)
-> D (age: 12)
-> E (age: 15)
-> G (age: 24)
-> C (age: 21)
-> E (age: 7)
-> A (age: 21)
-> D (age: 23)
-> C (age: 20)
I don't mind to much on the format of the return data, as long as it includes the nodes and relationship value between them. Something as simple as this is ideal:
A, D, 23
D, G, 25
But if its a nested array, I can parse it out on the function that wraps the query.