I'm trying to create relationships between nodes based on a Date property of thses nodes. A relationship like "NEXT" to visualize a sort of timeline of Nodes.
My graph looks like this :
And I would like to create "NEXT" relationships between "event" Nodes but only if they are linked to the same "topic" Node.
I ran the following cypher request to link the event Nodes for a single topic :
MATCH (e:event)-[r:CONCERNS]-(t:topic {name: 'topic1'})
WITH e ORDER BY e.dateEvent ASC
WITH COLLECT(e) AS events
FOREACH (n IN RANGE(0, SIZE(events)-2) |
FOREACH (prec IN [events[n]] |
FOREACH (next IN [events[n+1]] |
MERGE (prec)-[:NEXT]->(next))));
Unfortunaely, I didn't found the solution to run it for all the topics without creating a "NEXT" relationship betwwen event Nodes not linked ti the same Topic.
Hi clem,
Thx a lot for your reply.
In fact, I have the solution to create the relationships between all the Nodes:events linked to a single Node:topic. My problem is that I have thousands of different Nodes:topics and I don't know how to run this request through my entire graph.
I tried something like :
MATCH (tops:topic)
WITH tops
UNWIND tops AS top
MATCH (e:event)-[r:CONCERNS]-(t:topic {name: top.name})
WITH e ORDER BY e.dateEvent ASC
WITH COLLECT(e) AS events
FOREACH (n IN RANGE(0, SIZE(events)-2) |
FOREACH (prec IN [events[n]] |
FOREACH (next IN [events[n+1]] |
MERGE (prec)-[:NEXT]->(next))));
but it creates a relation between all the Nodes:event whatever they are linked to the same Nodes:topic or not
then you can do the query: MATCH(m:Movie)-[]->(n) // for all movies
or MATCH(m:SciFi)-[]->(n) // for only SciFi movies
or MATCH(m:Western:SciFi)-[]->(n) // for movies that are in both genres
And it's not hard to add a new label to existing Nodes. This is one of the great features of Neo4J (which I don't think is emphasized enough). In the Object Oriented Programming world, the analogous feature is called "multiple inheritance". However, in the OOP world, multiple inheritance is somewhat problematic, whereas in Neo4J it's pretty simple.
I hope that helps. (I haven't quite wrapped my head around your problem, though.)
Thanks a lot for your answer.
I'm not a developer, I'm a beginner with Neo4j and not as good as I'd like in English, so I think my explanations we're not clear enough (anyway, the possibility to have multiple labels for the same Node could be very useful for other use cases).
As you can see in my first snapshot, I have "Events" connected to "Topics", and I would like to create all the "NEXT" relationships between the "Events" with a single Cypher command.
The final result should be like the following snapshot :
I would try something like:
Make the lists of the connect events; get the head and tail of each list; connect the heads and tails.
You might be able to make a query to get all the Events that have no prior events (the head) and all the Events that have no next events (the tail) and glue those together. Then drop the first event from the list without a prior and the last event from the list without a next.
You can use ORDER BY to get the dates in order.
Being a newbie with Neo4J I sort of know what to do but not exactly....
Try this:
Step 1: Export the topic to a csv file:
CALL apoc.export.csv.query("
MATCH (tops:topic)
with distinct id(tops) as ID, tops.name as topic
RETURN ID, topc", "topics.csv", {})
This csv file will be in 'import' folder.
Step 2: Use LOAD CSV
LOAD CSV WITH HEADERS FROM "file:///topics.csv" AS row
WITH row
MATCH (t:topic) where id(t) = toInteger(row.ID)
MATCH (e:event)-[r:CONCERNS]-(t)
WITH e ORDER BY e.dateEvent ASC
WITH COLLECT(e) AS events
FOREACH (n IN RANGE(0, SIZE(events)-2) |
FOREACH (prec IN [events[n]] |
FOREACH (next IN [events[n+1]] |
MERGE (prec)-[:NEXT]->(next))))
First of all thanks a lot for your time and your ideas.
Finally, I found the solution based on your proposal.
The final cypher request to solve my problem is the following
MATCH (top:topic)
CALL
{
WITH top
MATCH (e:event)-[r:CONCERNS]-(t:topic {name: top.name})
WITH e ORDER BY e.dateEvent ASC
WITH COLLECT(e) AS events
FOREACH (n IN RANGE(0, SIZE(events)-2) |
FOREACH (prec IN [events[n]] |
FOREACH (next IN [events[n+1]] |
MERGE (prec)-[:NEXT]->(next))))
Return events
}
return top.name;