In my DB, my connections between item nodes are done through a three-way node-connection, like the one highlighted below. I chose it this way because I don't think there's a way to do a three-way arrow or relationship.
Anyways, I don't think this modeling is a problem in itself. But I would like to query this graph in a way that I ditch the CONNECTED_BY
relationship and collapse the connection path (e.g. the higlighted node in the picture) down to a simple relationship. How do I do it with Cypher in Neo4j?
I know there's the apoc.refactor.collapseNode
procedure, but, as far as I know, it actually mutates the database? Is there a way to use solely as a query? Not to mention that, in my case, I would have to omit the other relationships on the collapsed node somehow.
Here's an example of how to reproduce what I have:
// Users
// #1
CREATE (:User{name: "philippe_fanaro"});
CREATE (:User{name: "john_doe"});
// Items
// #1
MATCH (u:User{name: "john_doe"})
CREATE (u)-[:CREATED]->(:Item{title: "Designing Data-Intensive Applications"});
// #2
MATCH (u:User{name: "philippe_fanaro"})
CREATE (u)-[:CREATED]->(:Item{title: "System Design Interview – An insider's guide"});
// Connections
// #1
MATCH (i1:Item), (i2:Item), (u:User{name: "philippe_fanaro"})
WHERE i1.title CONTAINS "Designing"
AND i2.title CONTAINS "System"
CREATE (i1)- [:CONNECTION_ORIGIN]
->(c:Connection{title: "Relation"})
- [:CONNECTION_DESTINATION]->(i2),
(c)-[:CONNECTED_BY]->(u);
Not sure exactly what you want to query and what you want the result to be. But if you want to do something similar to apoc.refactor.collapseNode()
but as a virtual path instead of modifying the graph then maybe something like this could work (this query is based on the nodes and relationships you created in your example above with John Doe and Philippe Fanaro and creates a path from the "Designing"-book to the "System"-book with a virtual relationship called ":CONNECTION")?
MATCH (n1)-[:CONNECTION_ORIGIN]->(r)-[:CONNECTION_DESTINATION]->(n2)
WITH n1, apoc.create.vRelationship(n1, "CONNECTION", {}, n2) AS rel
RETURN apoc.path.create(n1, [rel])
Or, while adding the connection properties into the collapsed relationship and also returning the users:
MATCH (n1:Item)
-[:CONNECTION_ORIGIN]
->(r:Connection)
-[:CONNECTION_DESTINATION]
->(n2:Item),
(r)-[:CONNECTED_BY]-(u:User)
WITH u,
n1,
apoc.create.vRelationship(
n1,
"CONNECTION",
apoc.map.merge(
properties(r),
{ connected_by: u.id }
),
n2
) AS rel
RETURN u, apoc.path.create(n1, [rel])
Which yields the following: