cancel
Showing results for 
Search instead for 
Did you mean: 

Join the community at Nodes 2022, our free virtual event on November 16 - 17.

Cypher query for getting a subgraph by multiple relationship paths

lakshmi_rdk
Node Link

I am trying to write a cypher query to get a subgraph for a set of nodes by multiple relationship path. The subgraph I want to query looks like this.


Node1(Start node) is related to relatednodes, locations and actors. Actors are related to roles and movies.

The requirement is to fetch n nodes(which will be the start nodes of subgraph) with full subgraph. ( Given we know the relationship that we want to get in subgraph).
In my case get first 10 Node1 nodes and get the subgraph that is related by ACT_FOR, RELATED_TO, LOCATED_IN,HAS_ROLE, HAS_MOVIE

Query1 : Fetches nodes and subgraph as a flat list
Match(node:Node1)
WITH node
SKIP 0 LIMIT 10
OPTIONAL Match(node)-[avf:ACT_FOR]-(actor)
OPTIONAL Match(node)-[sa:RELATED_TO]->(relatednode)
OPTIONAL Match(node)-[li:LOCATED_IN]->(locatedin)
OPTIONAL MATCH(actor)-[db:HAS_ROLE]-(role)
OPTIONAL Match(actor)-[dt:HAS_MOVIE]->(movie)
RETURN node,actor,role,movie,relatednode,locatedin

Query 2: Fetches nodes and collect the result

Match(node:Node1)
WITH node
SKIP 0 LIMIT 10

OPTIONAL Match(node)-[avf:ACT_FOR]-(actor)
WITH node, actor
OPTIONAL Match(actor)-[db:HAS_ROLE]-(role)
OPTIONAL Match(actor)-[dt:HAS_MOVIE]->(movie) WITH node, actor, role, movie
With node, actor{.name, roles : collect ( role) , movies : collect(movie)} as actors
WITH node, collect(actors) as _actors

OPTIONAL Match(node)-[sa:RELATED_TO]->(relatednode)
With node, _actors , collect(relatednode) as _relatednodes

OPTIONAL Match(node)-[li:LOCATED_IN]->(locatedin)
WITH node, _actors , _relatednodes, collect(locatedin) as _locatedin
RETURN node, _actors , _relatednodes, _locatedin

The first query gives result as a flat table. Second one will aggregate the result but the query is too complicated and difficult to generalize. (I want to write a generalized query to get the subgraph for given nodes). Is there any other way to get subgraph for a set of nodes by multiple relationship? I came across apoc.subGraph , but that only supports single/different relationship to one target node. I am attaching sample data set.

MERGE (node1:Node1 {name: "Node1"})
MERGE (actor1:ACTOR {name: "actor1"})
MERGE (actor2:ACTOR {name: "actor2"})
MERGE (role1:ROLE {name: "role1"})
MERGE (role2:ROLE {name: "role2"})
MERGE (role3:ROLE {name: "role3"})
MERGE (movie1:MOVIE {name: "movie1"})
MERGE (relatednode1:Node1 {name: "relatednode1"})
MERGE (relatednode2:Node1 {name: "relatednode2"})
MERGE (location1:LOCATION {name: "location1"})

MERGE (node2:Node1 {name: "Node2"})
MERGE (actor3:ACTOR {name: "actor3"})
MERGE (actor4:ACTOR {name: "actor4"})
MERGE (role4:ROLE {name: "role4"})
MERGE (role5:ROLE {name: "role5"})
MERGE (role6:ROLE {name: "role6"})
MERGE (movie2:MOVIE {name: "movie2"})
MERGE (relatednode3:Node1 {name: "relatednode3"})
MERGE (relatednode4:Node1 {name: "relatednode4"})
MERGE (location2:LOCATION {name: "location2"})

MERGE (node3:Node1 {name: "Node3"})
MERGE (actor5:ACTOR {name: "actor5"})
MERGE (relatednode5:Node1 {name: "relatednode5"})

MERGE (node1)<-[:ACT_FOR]-(actor1)
MERGE (node1)<-[:ACT_FOR]-(actor2)
MERGE (actor1)-[:HAS_ROLE]->(role1)
MERGE (actor1)-[:HAS_ROLE]->(role2)
MERGE (actor2)-[:HAS_ROLE]->(role3)
MERGE (actor1)-[:HAS_MOVIE]->(movie1)
MERGE (actor2)-[:HAS_MOVIE]->(movie1)
MERGE (node1)-[:RELATED_TO]->(relatednode1)
MERGE (node1)-[:RELATED_TO]->(relatednode2)
MERGE (node1)-[:LOCATED_IN]->(location1)

MERGE (node2)<-[:ACT_FOR]-(actor3)
MERGE (node2)<-[:ACT_FOR]-(actor4)
MERGE (actor3)-[:HAS_ROLE]->(role4)
MERGE (actor3)-[:HAS_ROLE]->(role5)
MERGE (actor4)-[:HAS_ROLE]->(role6)
MERGE (actor3)-[:HAS_MOVIE]->(movie2)
MERGE (actor4)-[:HAS_MOVIE]->(movie2)
MERGE (node2)-[:RELATED_TO]->(relatednode3)
MERGE (node2)-[:RELATED_TO]->(relatednode4)
MERGE (node2)-[:LOCATED_IN]->(location2)

MERGE (node3)<-[:ACT_FOR]-(actor5)
MERGE (node3)-[:RELATED_TO]->(relatednode5)

8 REPLIES 8

Joel
Ninja
Ninja

There appear to be several different questions here, you mention subgraph several times, and that is the visual, so I'll start there.

A simplified cypher to match the first 10 ('Node1' labeled nodes) and the nodes they are connected to (with just the relationships in your list). Note: the variable p contains paths

match (node:Node1) with node limit 10
match p=(node)-[:ACT_FOR|RELATED_TO|LOCATED_IN|HAS_ROLE|HAS_MOVIE*..1]-(n2)
RETURN p


Note, in this example the number one in *..1 tells cypher the max path length, so if you want more of each subgraph (as shown in your graphic), you'll need to increase the path length

match (node:Node1) with node limit 10
match p=(node)-[:ACT_FOR|RELATED_TO|LOCATED_IN|HAS_ROLE|HAS_MOVIE*..2]-(n2)
RETURN p

which returns this

There are additional ways to do it, but this option seems easier to read and understand.

But the result of the query you provided is a flat lists of nodes. I want to get the nodes and the relationship paths so that I can construct the graph(in the UI). Consider that there is an API which accepts type of node and relationships. Based on API input cypher query need to be executed and return an API response that will be used to create the subgraph in UI ( which will be similar to the visual I provided ).

Try this:
Start with your 'actor1' node and select maxLevel and in your case it should be 3. When you run this query this should show the graph you are looking for. Also, you can export the query results to a json file.

MATCH (c) WHERE c.name = "actor1"
CALL apoc.path.subgraphAll(c, {maxLevel: 3}) YIELD nodes, relationships 
RETURN nodes, relationships


mj2748043610
Node Clone

Hello, have you solved your problem? Your task is similar to my project, which aims at searching the similar subgraph from database with the cypher statement.

You can export the results json file and use that to create the subgraph.

MATCH (c) WHERE c.name = "actor1"
CALL apoc.path.subgraphAll(c, {maxLevel: 3}) YIELD nodes, relationships 
RETURN nodes, relationships

WITH [ node in nodes | node {.*, label:labels(node)[0], id:tostring(id(node))}] as nodes, [rel in relationships 
| rel {.*, fromNode:{label:labels(startNode(rel))[0], id:tostring(id(startNode(rel)))},type:type(rel), toNode:{label:labels(endNode(rel))[0], id:tostring(id(endNode(rel)))}}] as rels 
WITH {nodes:nodes, relationships:rels} as json 
RETURN apoc.convert.toJson(json)

Thanks! However, the subgraphall function can't specify the relationship types among nodes, because I want to search the subgraphs similar to the target subgraph from database. Do you have any idea about this topic? Thanks again.

I replied to your question on exporting the data. Please describe your problem so that I can help. Post your queries.

Hello, thanks for your reply!
(1)My target: To Search the isomophic subgraphs from the database with the cypher.
Inputing the cypher queries to return the nodes and relationships of all matched subgraphs.

(2)For example
The target subgraph is:
3X_f_7_f74038cf4cba12554803ac47e718623585758936.png

There are two types of nodes: road and junction and one type of relationship: LINK_WITH. The three road nodes are linked with each other, and they are all linked to the node junction.

Therefore, the cypher describes the nodes and relationships of the target subgraph, which restricts the types of nodes and the specified connected relationships (also specified nodes and relationship properties).

The cypher is:

match p1=(road1:Road)-[link1:LINK_WITH]-(road2:Road)-[link2:LINK_WITH]-(road3:Road),p2=(road1)-[link3:LINK_WITH]-(road3)
where 100<=link1.angle<=120 and 100<=link2.angle<=120 and 100<=link3.angle<=140
with road1, road2, road3, p1,p2
match p3=(road1)-[:LINK_WITH]-(jun:Junction)-[:LINK_WITH]-(road2)
with road1, road2, road3, jun,p1,p2,p3
match p4=(road2)-[:LINK_WITH]-(jun)-[:LINK_WITH]-(road3)
with road1,road2,road3, jun,p2,p1,p3,p4
match p5=(road3)-[:LINK_WITH]-(jun)-[:LINK_WITH]-(road1)
with road1,road2,road3, jun,p3,p1,p2,p4,p5
with collect(distinct road1) as cr1, collect(distinct road2) as cr2, collect(distinct road3) as cr3,collect(distinct jun) as cj, collect(distinct p1) as cp1,collect(distinct p2) as cp2,collect(distinct p3) as cp3,collect(distinct p4) as cp4,collect(distinct p5) as cp5
return cr1,cr2,cr3,cj,cp1,cp2,cp3,cp4,cp5

The matched subgraphs are:


The table is:

(3)My problems:
First, I'm not sure whether the similar subgraphs within database are all matched .
Second, the cypher is complex, is there any concise and effective statement?
Third, the returned result is comolex, how to get nodes and relationships that can be phrased in .net driver simply.
Fourth, are there any tools that can match subgraphs directly and return the nodes and relationships. The apoc and gds library can't solve this problem, as far as I know, because they can't specify the relationships among specified nodes.
At last, thank you for sparing time reading my problems! I expect for your reply! Thanks again.