I would like to write a query for the graph below, which should return three lists, each list containing all persons working for the same person.
Given the graph below, the result should be this three lists:
[Fritz]
[Pepe]
[Susy, Peter]
I fail to write such query. My query returns all employes in one list.
The following statements create the graph model for the example I have given:
MATCH (c:Example) DETACH DELETE c;
CREATE (p1:Parent:Example {id: 1, name: 'Andy', title: 'Developer'});
CREATE (p2:Parent:Example {id: 2, name: 'Lila', title: 'Developer'});
CREATE (p3:Parent:Example {id: 3, name: 'Lula', title: 'Developer'});
CREATE (c11:Child:Example {id: 11, name: 'Peter', title: 'Developer'});
CREATE (c12:Child:Example {id: 12, name: 'Susy', title: 'Developer'});
CREATE (c21:Child:Example {id: 21, name: 'Fritz', title: 'Developer'});
CREATE (c31:Child:Example {id: 31, name: 'Pepe', title: 'Developer'});
MATCH (p {id: 1}), (c {id: 11}) MERGE (p)<-[:WORKS_FOR]-(c);
MATCH (p {id: 1}), (c {id: 12}) MERGE (p)<-[:WORKS_FOR]-(c);
MATCH (p {id: 2}), (c {id: 21}) MERGE (p)<-[:WORKS_FOR]-(c);
MATCH (p {id: 3}), (c {id: 31}) MERGE (p)<-[:WORKS_FOR]-(c);
It's relatively straightforward with Cypher
MATCH (c)-[:WORKS_FOR]->(p)
RETURN p.name AS boss, collect(c.name) AS coWorkers
Result
╒══════╤════════════════╕
│"boss"│"coWorkers" │
╞══════╪════════════════╡
│"Andy"│["Peter","Susy"]│
├──────┼────────────────┤
│"Lila"│["Fritz"] │
├──────┼────────────────┤
│"Lula"│["Pepe"] │
└──────┴────────────────┘
The trick is understanding aggregations https://neo4j.com/docs/cypher-manual/current/functions/aggregating/#grouping-keys
I have two users:
CREATE (a:user {id: 1})
CREATE (b:user {id: 2})
I want users to be able to follow each other:
MATCH (a:user {id: 1}), (b:user {id: 2})
CREATE (a)-[r:FOLLOWS]->(b)
But I also need to keep track of when that follow happened:
MATCH (a:user {id: 1}), (b:user {id: 2})
CREATE (a)-[r:FOLLOWS {t: 32409823}]->(b)
My issue is that I need create the :FOLLOWS relation if it does not already exist without making a query to check, then another query to create it. Ideally CREATE UNIQUE would solve this, which works just fine without any changing fields on the relation:
MATCH (a:user {id: 1}), (b:user {id: 2})
CREATE UNIQUE (a)-[r:FOLLOWS]->(b)
(THIS WORKS)
But when I include a timestamp on the relation, create unique will make a second relation because it has a different timestamp.
MATCH (a:user {id: 1}), (b:user {id: 2})
CREATE UNIQUE (a)-[r:FOLLOWS {t: 32409823}]->(b)
(THIS DOESN'T WORK)
The above creates a new relation every time because the timestamp is always changing. Is there any way I can check if any relation with the label :FOLLOWS exists and create the relation with fields if it doesn't?
MERGE and its ON CREATE clause should do what you want. MERGE will match on the :FOLLOWS relationship, and if it does not exist it will create it. ON CREATE is only performed if the MERGE operation created the relationship instead of matching on an existing one.
MATCH (a:user {id: 1}), (b:user {id: 2})
MERGE (a)-[r:FOLLOWS]->(b)
ON CREATE SET r.t = timestamp()
I'm creating test database for transport in a city.
My goal find path betweeb any stops.
I created this graph:
create (Stop_13_1:Tram {Id: 131}),
(Stop_13_2:Tram {Id: 132}),
(Stop_26_1:Tram {Id: 261}),
(Stop_26_2:Tram {Id: 262}),
(Stop_26_3_13_3:Tram {Id: 263133}),
(Stop_26_4_13_4:Tram {Id: 264134}),
(Stop_26_5_13_5:Tram {Id: 265135}),
(Stop_26_6_13_6:Tram {Id: 266136}),
(Stop_26_7_13_7:Tram {Id: 267137}),
(Stop_26_8:Tram {Id: 268}),
(Stop_7_1:Trollebus {Id: 71}),
(Stop_7_2:Trollebus {Id: 72}),
(Stop_7_3:Trollebus {Id: 73}),
(Stop_7_4:Trollebus {Id: 74}),
(Stop_7_5:Trollebus {Id: 75});
When I try find short way:
match p=shortestPath((a)-[:TO*]-(c))
where a.Id=131 and c.Id=268
return p, length(p) limit 1
Or this query:
MATCH (p1:Tram {id: 131}), (p2:Tram {id: 263133}),
path = shortestpath((p1)-[:NEXT*]-(p2))
RETURN path
It's doesn't show any route.
Can you please help me edit query?
P.S. I forgot add relation:
MATCH (Stop_13_1 {Id: 131}),
(Stop_13_2 {Id: 132}),
(Stop_26_1 {Id: 261}),
(Stop_26_2 {Id: 262}),
(Stop_26_3_13_3 {Id: 263133}),
(Stop_26_4_13_4 {Id: 264134}),
(Stop_26_5_13_5 {Id: 265135}),
(Stop_26_6_13_6 {Id: 266136}),
(Stop_26_7_13_7 {Id: 267137}),
(Stop_26_8 {Id: 268}),
(Stop_7_1 {Id: 71}),
(Stop_7_2 {Id: 72}),
(Stop_7_3 {Id: 73}),
(Stop_7_4 {Id: 74}),
(Stop_7_5 {Id: 75})
MERGE (Stop_13_1)- [:NEXT{distance:4.7,route:13,transport:'tram',direct:'down'}]->(Stop_13_2)
MERGE (Stop_13_2)-[:NEXT{distance:4.7,route:13,transport:'tram',direct:'up'}]->(Stop_13_1)
MERGE (Stop_13_2)-[:NEXT{distance:3.7,route:13,transport:'tram',direct:'down'}]->(Stop_26_3_13_3)
MERGE (Stop_26_3_13_3)-[:NEXT{distance:3.7,route:13,transport:'tram',direct:'up'}]->(Stop_13_2)
MERGE (Stop_26_1)-[:NEXT{distance:5.8,route:26,transport:'tram',direct:'down'}]->(Stop_26_2)
MERGE (Stop_26_2)-[:NEXT{distance:5.8,route:26,transport:'tram',direct:'up'}]->(Stop_26_1)
MERGE (Stop_26_2)-[:NEXT{distance:2.5,route:26,transport:'tram',direct:'down'}]->(Stop_26_3_13_3)
MERGE (Stop_26_3_13_3)-[:NEXT{distance:2.5,route:26,transport:'tram',direct:'up'}]->(Stop_26_2)
MERGE (Stop_26_3_13_3)-[:NEXT{distance:3.1,route:26,route:13,transport:'tram',direct:'down'}]->(Stop_26_4_13_4)
MERGE (Stop_26_4_13_4)-[:NEXT{distance:3.1,route:26,route:13,transport:'tram',direct:'up'}]->(Stop_26_3_13_3)
MERGE (Stop_26_4_13_4)-[:NEXT{distance:5.8,route:26,route:13,transport:'tram',direct:'down'}]->(Stop_26_5_13_5)
MERGE (Stop_26_5_13_5)-[:NEXT{distance:5.8,route:26,route:13,transport:'tram',direct:'up'}]->(Stop_26_4_13_4)
MERGE (Stop_26_5_13_5)-[:NEXT{distance:10.8,route:26,route:13,transport:'tram',direct:'down'}]->(Stop_26_6_13_6)
MERGE (Stop_26_6_13_6)-[:NEXT{distance:10.8,route:26,route:13,transport:'tram',direct:'up'}]->(Stop_26_5_13_5)
MERGE (Stop_26_6_13_6)-[:NEXT{distance:2.5,route:26,route:13,transport:'tram',direct:'down'}]->(Stop_26_7_13_7)
MERGE (Stop_26_7_13_7)-[:NEXT{distance:2.5,route:26,route:13,transport:'tram',direct:'up'}]->(Stop_26_6_13_6)
MERGE (Stop_26_5_13_5)-[:NEXT{distance:0.6,transport:'walking',direct:'down'}]->(Stop_7_2)
MERGE (Stop_7_2)-[:NEXT{distance:0.6,transport:'walking',direct:'up'}]->(Stop_26_5_13_5)
MERGE (Stop_26_8)-[:NEXT{distance:1,route:26,transport:'tram',direct:'down'}]->(Stop_26_7_13_7)
MERGE (Stop_26_7_13_7)-[:NEXT{distance:1,route:26,transport:'tram',direct:'up'}]->(Stop_26_8)
MERGE (Stop_7_1)-[:NEXT{distance:2.2,route:7,transport:'trolleybus',direct:'down'}]->(Stop_7_2)
MERGE (Stop_7_2)-[:NEXT{distance:2.2,route:7,transport:'trolleybus',direct:'up'}]->(Stop_7_1)
MERGE (Stop_7_2)-[:NEXT{distance:1.6,route:7,transport:'trolleybus',direct:'up'}]->(Stop_7_3)
MERGE (Stop_7_3)-[:NEXT{distance:2.5,route:7,transport:'trolleybus',direct:'up'}]->(Stop_7_4)
MERGE (Stop_7_4)-[:NEXT{distance:3.1,route:7,transport:'trolleybus',direct:'down'}]->(Stop_7_5)
MERGE (Stop_7_5)-[:NEXT{distance:4.4,route:7,transport:'trolleybus',direct:'down'}]->(Stop_7_2)
You are trying to match shortest paths that have a TO relationship, however your graph shows that the type of the relationship is NEXT.
I replicated your graph here http://console.neo4j.org/r/boin78
And the following query is working as expected by just specifying the correct relationship type :
match p=shortestPath((a)-[:NEXT*]-(c))
where a.Id=131 and c.Id=268
return p, length(p)
limit 1
For the second query, you used the id as property while your nodes have the Id property name, the following is working :
MATCH (p1:Tram {Id: 131}), (p2:Tram {Id: 263133}),
path = shortestpath((p1)-[:NEXT*]-(p2))
RETURN path
Having a graph where molecules are attached to a common scaffold with [:substructureOf] relationships and where similar molecules are connected to eachothers with a [:isSimilarTo] relationship, is the a way to return all [:isSimilarTo] relationships for a specific subset of molecules?
In pseudo cypher code, considering m as a collection (subset of molecules), I would like to assess that m1 and m2 of each sim relationship is part of m
MATCH (:Scaffold {Name: 'A'}) <-[:usbstructureOf]- (m:Molecule)
WITH m MATCH (m1:Molecule) -[sim:isSimilarTo]- (m2:Molecule)
WHERE m1 IN m AND m2 IN m
Is there a proper cypher way to write this? Example dataset below.
CREATE (:Scaffold {Name: 'A'});
CREATE (:Scaffold {Name: 'B'});
MATCH (s:Scaffold {Name: 'A'}) MERGE (s) -[:substructureOf]->(:Molecule {Name: 'm1'});
MATCH (s:Scaffold {Name: 'A'}) MERGE (s) -[:substructureOf]->(:Molecule {Name: 'm2'});
MATCH (s:Scaffold {Name: 'A'}) MERGE (s) -[:substructureOf]->(:Molecule {Name: 'm3'});
MATCH (s:Scaffold {Name: 'A'}) MERGE (s) -[:substructureOf]->(:Molecule {Name: 'm4'});
MATCH (s:Scaffold {Name: 'B'}) MERGE (s) -[:substructureOf]->(:Molecule {Name: 'm5'});
MATCH (m:Molecule {Name: 'm1'}), (n:Molecule {Name: 'm2'}) CREATE (m) -[isSimilarTo]-> (n);
MATCH (m:Molecule {Name: 'm1'}), (n:Molecule {Name: 'm3'}) CREATE (m) -[isSimilarTo]-> (n);
MATCH (m:Molecule {Name: 'm2'}), (n:Molecule {Name: 'm3'}) CREATE (m) -[isSimilarTo]-> (n);
MATCH (m:Molecule {Name: 'm3'}), (n:Molecule {Name: 'm4'}) CREATE (m) -[isSimilarTo]-> (n);
MATCH (m:Molecule {Name: 'm4'}), (n:Molecule {Name: 'm5'}) CREATE (m) -[isSimilarTo]-> (n);
I still don't fully understand what you want, a network scheme/drawing might help next time.
But I think what you want is similar molecules sharing the same scaffold. I.e. all Molecule pairs connected by isSimilarTo edges, where both Molecules are linked to a defined Scaffold.
You can get this by matching the complete path:
(Scaffold)--(Molecule)--(similar Molecule)--(same Scaffold)
In Cypher:
MATCH (s:Scaffold {Name: 'A'})<-[:isbstructureOf]-(m1:Molecule)
-[sim:isSimilarTo]-(m2:Molecule)-[:isbstructureOf]->(s)
// Return the relationships
RETURN DISTINCT m1.name, sim.value, m2.name
// Return count of relationships
RETURN count(DISTINCT sim)
Alternative answer:
MATCH (s:Scaffold {Name: 'A'})-[:substructureOf*]->(m:Molecule)
WITH collect(m) as mols MATCH p=(:Molecule) -[sim:isSimilarTo]- (:Molecule)
WHERE startNode(r) IN mols and endNode(r) IN mols
RETURN p
The overall path is shorter.
I am new to cypher. I want to find similar nodes without repeating matches.
Sample data
CREATE (r1:Repository {id:"repository1"})
CREATE (r2:Repository {id:"repository2"})
CREATE (r3:Repository {id:"repository3"})
CREATE (a1:Actor {id: "actor1"})
CREATE (a2:Actor {id: "actor2"})
CREATE (a3:Actor {id: "actor3"})
CREATE (o1:Organization {id:"organization1"})
CREATE (o2:Organization {id:"organization2"})
MATCH (a:Repository {id:"repository1"}) MATCH (b:Actor {id: 'actor1'})
CREATE (a)-[:IS_ACTOR]->(b)
MATCH (a:Repository {id:"repository1"}) MATCH (b:Actor {id: 'actor2'})
CREATE (a)-[:IS_ACTOR]->(b)
MATCH (a:Repository {id:"repository1"}) MATCH (b:Actor {id: 'actor3'})
CREATE (a)-[:IS_ACTOR]->(b)
MATCH (a:Repository {id:"repository1"}) MATCH (b:Organization {id:
'organization1'}) CREATE (a)-[:IN_ORGANIZATION]->(b)
MATCH (a:Repository {id:"repository2"}) MATCH (b:Actor {id: 'actor1'})
CREATE (a)-[:IS_ACTOR]->(b)
MATCH (a:Repository {id:"repository2"}) MATCH (b:Actor {id: 'actor2'})
CREATE (a)-[:IS_ACTOR]->(b)
MATCH (a:Repository {id:"repository2"}) MATCH (b:Organization {id:
'organization1'}) CREATE (a)-[:IN_ORGANIZATION]->(b)
MATCH (a:Repository {id:"repository3"}) MATCH (b:Actor {id: 'actor3'})
CREATE (a)-[:IS_ACTOR]->(b)
MATCH (a:Repository {id:"repository3"}) MATCH (b:Organization {id:
'organization2'}) CREATE (a)-[:IN_ORGANIZATION]->(b)
Cypher
MATCH (a)-[r1:IS_ACTOR|IN_ORGANIZATION]->(match)<-
[r2:IS_ACTOR|IN_ORGANIZATION]-(b)
where not a.id = b.id with a,b,count(match) as count, collect (match.id) as
connections, collect (type(r1)) as rel1
return a.id,b.id,count,connections,rel1 order by count desc
Result
a.id b.id count connections rel1
repository2 repository1 3 actor1,actor2,organization1 IS_ACTOR, IS_ACTOR,IN_ORGANIZATION
repository1 repository2 3 actor1,actor2,organization1 IS_ACTOR, IS_ACTOR,IN_ORGANIZATION
repository3 repository1 1 actor3 IS_ACTOR
repository1 repository3 1 actor3 IS_ACTOR
How can I remove row #2 & #4 from the result?
Based on response to a similar question I tried using filter but I get syntax error (cypher below)
MATCH (a)-[r1:IS_ACTOR|IN_ORGANIZATION]->(match)<-
[r2:IS_ACTOR|IN_ORGANIZATION]-(b)
with filter(x in connections where x <> b.id)
where not a.id = b.id with a,b,count(match) as count, collect (match.id) as
connections, collect (type(r1)) as rel1
return a.id,b.id,count,connections,rel1 order by count desc
You match the path once from both sides, something that you can do to force only one of those paths to be returned. Compare the id's so you put a and b in a fixed order and avoid the other combo.
MATCH (a)-[r1:IS_ACTOR|IN_ORGANIZATION]->(match)
<-[r2:IS_ACTOR|IN_ORGANIZATION]-(b)
where id(a) > id(b)
with a,b,count(match) as count,
collect (match.id) as connections, collect (type(r1)) as rel1
return a.id,b.id,count,connections,rel1 order by count desc