Finding the full network connected with a node in neo4j - graph

Suppose I have a neo4j graph with 3 different kind of nodes (say type A, type B, type C).
There are :
5 nodes of type A
40 nodes of type B
200 nodes of type C
Each node of type A are connecting to one or more of type B ((A -> B)) and each node of type B are connecting to one or more of type C ((B -> C)).
One node of type B can be shared by more than one type A nodes (A1 -> B1, A2 -> B1) and one node of type C can be shared by more than one type B nodes (B1 -> C1, B2 -> C1).
No node of type A connects with any node of type C. And the relationships are directional as described above.
For a given node of type A, can I find out all the nodes in the connected network, i.e., the entire tree emerging from that node, and not just the immediately connected nodes?
So basically I am looking for a py2neo function or cypher query that can give me a full tree or full network emerging from a given node.

Is this query respond to your needs ?
MATCH p=(a:A)-->(b:B)-->(c:C)
WHERE a.id = 'your id' // your condition to find your specific A node
RETURN p

Related

Why is a sum (or discriminated union or disjoint union) the inverse of a product?

I'm trying to wrap my head around category theory and this question just came to my mind - why is the sum type the inverse of the product type? I mean, I see how arrows are changing directions in the opposite category, but I don't see why sum couldn't contain both components coming to it.
They are dual in the sense that one is defined by the mapping in property, and the other by the mapping out property. Every mapping into a product, c -> (a, b), is equivalent to a pair of functions c -> a and c -> b. Every mapping out of a coproduct, Either a b -> c is equivalent to a pair of functions a -> c and b -> c (think of pattern matching the Left a and Right b constructors).

Neo4j Creating relationship between nodes that already map to a relationship

Currently, I have a query in Neo4j that returns all the nodes in my graph that are pointed to by multiple nodes.
The query to return these nodes (in picture) looks like this:
MATCH (n)-[r:CLINICAL_SIGNIFICANCE]->()
WITH n, count(r) as rel_cnt
WHERE rel_cnt > 1
MATCH (c)-[r:PROTEIN_CHANGE]->(n)
return c, n
Is there a way to loop through the nodes labeled as c (blue nodes) and if they point to the same node labeled as n (yellow nodes), create a relationship between the nodes labeled as c (blue nodes)?

Get all childs of a particular node till a particular depth

I have this relationship in my neo4j:
Parent -> Childs
F -> D,E
D -> A,B,C
A -> X
Use case: I am trying to get all child of a particular node using this query till a particular depth let's say depth = 2
Query to get All child of node F
MATCH (p:Person)-[:REPORTS_TO *]->(c:Person) WHERE p.name="F"
WITH COLLECT (c) + p AS all
UNWIND all as p MATCH (p)-[:REPORTS_TO]-(c)
RETURN p,c;
This returns me this: (which is all child's node of F without limit)
But when I try to get all childs till depth 2 :
Query to get All child of node F with depth = 2
MATCH (p:Person)-[:REPORTS_TO *2]->(c:Person) WHERE p.name="F"
WITH COLLECT (c) + p AS all
UNWIND all as p MATCH (p)-[:REPORTS_TO]->(c)
RETURN p,c;
Which returns
When I put depth = 2, it didn't return all child's of D' (only returned A and notB`, 'C')
Expected response was:
All child's of 'F', child's of all child's of `F' (i.e level 1) and child's of all childs of nodes of level 1 (i.e level 2)
Am I missing something in my query or any another way to get a response as I expected above?
Adding dataset
CREATE (f:Person {name: "F"})
CREATE (e:Person {name: "E"})
CREATE (d:Person {name: "D"})
CREATE (c:Person {name: "C"})
CREATE (b:Person {name: "B"})
CREATE (a:Person {name: "A"})
CREATE (x:Person {name: "X"})
CREATE (a)-[:REPORTS_TO]->(x)
CREATE (d)-[:REPORTS_TO]->(a)
CREATE (d)-[:REPORTS_TO]->(b)
CREATE (d)-[:REPORTS_TO]->(c)
CREATE (f)-[:REPORTS_TO]->(d)
CREATE (f)-[:REPORTS_TO]->(e)
The problem is you're not querying for what you think you're querying for.
[:REPORTS_TO *2]
doesn't query up to depth 2, it queries nodes at exactly depth 2. The result is nodes B, C, A, and F (since you added it in).
Of those nodes, only nodes A and F have an outgoing :REPORTS_TO relationship, so your match eliminates B and C from the result set. The nodes returned are A and F and the nodes reachable by an outgoing :REPORTS_TO relationship (E, D, and X).
If you want to alter your query so it's up to depth 2 instead of exactly depth 2, use a range on the variable-length relationship (omitting the lower-bound makes it default to 1):
[:REPORTS_TO *..2]
And if you want this to include F in the match itself (instead of manually adding it when you collect the nodes), use a lower bound of 0:
[:REPORTS_TO *0..2]

Finding an edge by unique ID or name

It is possible to search a subgraph and node by their unique names;
n = agnode(g, "myUniqueNodeName", FALSE);
h = agsubg(g, "myUniqueSubgrahName", FALSE);
Likewise, is there a way to search edges in a strict directed graph by their unique names?
e = agedge (g, u, v, "e28", FALSE);
Documentation indicates that:
The 'name' of an edge (more correctly, identifier) is treated as a
unique indentifier for edges between a particular node pair. That is,
there can only be at most one edge with name e28 between any given u
and v, but there can be many other edges between other nodes.
It seems that there must be a list of edges that can be searched by name. Otherwise, a separate (ID -> edge) map will need to be maintained separately.

Finding Subgraph in a Graph

I have a graph shown here. Just to node that nodes B_0, B_1, belong to node of type B, C_0, C_1. C_2, C_3 belong to node of type C and so on.
Now, I want to find multiple subgraphs, which could satify criteria like defined by this example -
Criteria -
subgraph contains 1 node of type A, 1 node of type B, 1 node of type C, one node of type D.
subgraph has one edge from node of type A to one node of type B, one edge connecting type B and type C and one node connecting type C and type D.
subgraph contains one edge from type A going out of subgraph to type B node, one edge
from type B to type C node outside, one edge from type D to type E outside.
Now this description should give result as -
subgraph :: A_0, B_0, C_1, D_1
subgraph :: A_0, B_0, C_0, D_0
subgraph :: A_0, B_1, C_2, D_2
subgraph :: A_0, B_1, C_3, D_3
I want to know, if there is any algorithm, by which I can find such sub-graphs?
I tried to figure out an algorithm by making all possible combinations. However, this would be exponential to number of nodes in subgraph. Thus, I want to know if there exists an efficient way to calculate it. Or if there exists a problem of similar nature in Graph Theory?
You can start by visiting all nodes of type A. For each A node, look at all nodes connected to it which are of type B. From there look all nodes of type C and so on, keeping track of the nodes you've visited from the last A node. Then whenever you reach a subnode that completes the criteria of your search, you add all the list of nodes from the A node until the point where you are. Essentially you're doing a depth-first search where you keep traversing into the graph as long as a node meets the criteria of what should follow and backtrack whenever there's no more valid nodes (ie. which would produce a valid subgraph) going out from your current node.

Resources