Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
11-14-2022 01:01 PM
Hi there,
I am trying to (dynamically) collapse/reduce certain parts of a graph to reduce the amount of nodes/rels in the output to the user.
This is a small sample of my dataset:
CREATE (c1:Connection {name: 'C1'})
CREATE (c2:Connection {name: 'C2'})
CREATE (c3:Connection {name: 'C3'})
CREATE (f1:File {name: 'F1'})
CREATE (f2:File {name: 'F2'})
CREATE (f3:File {name: 'F3'})
CREATE (f4:File {name: 'F4'})
CREATE (f5:File {name: 'F5'})
CREATE (f6:File {name: 'F6'})
CREATE (m1:Monitor {name: 'M1'})
MERGE (c1)-[:RECEIVES]->(f1)
MERGE (c2)-[:RECEIVES]->(f2)
MERGE (c2)-[:RECEIVES]->(f3)
MERGE (f1)<-[:MONITORS]-(m1)
MERGE (f2)<-[:MONITORS]-(m1)
MERGE (f3)<-[:MONITORS]-(m1)
MERGE (f4)<-[:MONITORS]-(m1)
MERGE (f5)<-[:MONITORS]-(m1)
MERGE (f6)<-[:MONITORS]-(m1)
MERGE (f4)-[:SENDS]->(c3)
MERGE (f5)-[:SENDS]->(c3)
MERGE (f6)-[:SENDS]->(c3)
Which looks like this:
And what I want is something like this:
Where the aggregated relations would contain the number of relations it aggregated (so C1->M1 = 1, C2->M1 = 2, M1->C3 = 3).
I have tried using both ` apoc.create.vRelationship` and ` apoc.nodes.collapse` but I am unable to obtain my desired result. I can always resort to computing the aggregated relations and store them in the DB, but I would really like to avoid that as it requires me to rerun that computation each time new data is inserted into the DB.
Would anyone be able to help me on this? Let me know if I should provide more information.
Solved! Go to Solution.
11-14-2022 02:38 PM
My mistake. I forgot to import 'm' into the call subquery, so each match was not constrained to 'M1'.
Try this:
match(m:Monitor{name:"M1"})
call{
with m
match(m)--()-[:RECEIVES]-(c:Connection)
with m, c, count(*) as cnt
CALL apoc.create.vRelationship(c,'RECEIVES_AGG',{number:cnt},m) YIELD rel
return c, rel
union
with m
match(m)--()-[:SENDS]-(c:Connection)
with m, c, count(*) as cnt
CALL apoc.create.vRelationship(m,'SENDS_AGG',{number:cnt},c) YIELD rel
return c, rel
}
return *
11-14-2022 01:26 PM
Try this:
match(m:Monitor{name:"M1"})
call{
match(m)--()-[:RECEIVES]-(c:Connection)
with m, c, count(*) as cnt
CALL apoc.create.vRelationship(c,'RECEIVES_AGG',{number:cnt},m) YIELD rel
return c, rel
union
match(m)--()-[:SENDS]-(c:Connection)
with m, c, count(*) as cnt
CALL apoc.create.vRelationship(m,'SENDS_AGG',{number:cnt},c) YIELD rel
return c, rel
}
return *
11-14-2022 02:31 PM
Hi glilienfield,
Thank you for the quick response!
I tried your query and I think I'm almost there. In my actual dataset, there are numerous other nodes (with similar structures/flow as this example).
If you add the following data (an another completely unrelated subgraph):
MERGE (c4:Connection {name: 'C4'})-[:RECEIVES]->(f7:File {name: 'F7'})<-[:MONITORS]-(m2:Monitor {name: 'M2'})-[:MONITORS]->(f8:File {name: 'F8'})-[:SENDS]->(c5:Connection {name: 'C5'})
You'll see your query returning this:
I don't get why this happens; we only match connections that are connected to M1 right? How are Connection nodes from another Monitor/subgraph then returned as well?
11-14-2022 02:38 PM
My mistake. I forgot to import 'm' into the call subquery, so each match was not constrained to 'M1'.
Try this:
match(m:Monitor{name:"M1"})
call{
with m
match(m)--()-[:RECEIVES]-(c:Connection)
with m, c, count(*) as cnt
CALL apoc.create.vRelationship(c,'RECEIVES_AGG',{number:cnt},m) YIELD rel
return c, rel
union
with m
match(m)--()-[:SENDS]-(c:Connection)
with m, c, count(*) as cnt
CALL apoc.create.vRelationship(m,'SENDS_AGG',{number:cnt},c) YIELD rel
return c, rel
}
return *
11-14-2022 03:05 PM
Yes that works, thanks!
All the sessions of the conference are now available online