Reputation: 25
I have a Cypher query that goes something like this:
MATCH (t1:Team)-[:PLAYS_ON]->(m:Match)<-[:PLAYS_ON]-(t2:Team)
RETURN t1 AS "Team 1", m AS "Match", t2 as "Team 2"
My goal is to have a query that allows me to see matches and which teams are matching eachother in a deportive context.
Assuming Team 1, Team 2 and Team 3, and the matches being Team 1 vs Team 2 and Team 2 vs Team 3, my expected output is:
+------+-----+------+
|Team 1|match|Team 2|
|------+-----+------|
|Team 1|date |Team 2|
|Team 2|date |Team 3|
+------+-----+------+
But I get:
+------+-----+------+
|Team 1|match|Team 2|
|------+-----+------|
|Team 1|date |Team 2|
|Team 2|date |Team 1|
|Team 2|date |Team 3|
|Team 3|date |Team 2|
+------+-----+------+
I'm relatively new to Cypher/Neo4J, so, I would not be impressed if it turns out i'm commiting a very obvious and stupid mistake, but I don't have the brains to see it.
Thank you for your answers!
Upvotes: 0
Views: 37
Reputation: 495
An alternative way to achieve what you want is this query (using Nimrod Serok's graph):
MATCH (t1:Team)-[:PLAYS_ON]->(m:Match)<-[:PLAYS_ON]-(t2:Team)
WHERE id(t1) < id(t2)
RETURN t1, m, t2
This works because the WHERE
clause ensures that the same team pairing doesn't get considered in both directions (which causes the cartesian product).
Upvotes: 0
Reputation: 16033
One way to do it is:
MATCH (t:Team)-[:PLAYS_ON]->(m:Match)
WITH collect(t) AS t, m
RETURN t[0] AS t1, m, t[1] AS t2
Which on this sample data:
MERGE (a:Team{name: 'Team1'})
MERGE (b:Team{name: 'Team2'})
MERGE (c:Team{name: 'Team3'})
MERGE (d:Match{Date: '2022-05-11'})
MERGE (e:Match{Date: '2022-05-12'})
MERGE (a)-[:PLAYS_ON]-(d)
MERGE (b)-[:PLAYS_ON]-(d)
MERGE (b)-[:PLAYS_ON]-(e)
MERGE (c)-[:PLAYS_ON]-(e)
Will give you this:
╒════════════════╤═════════════════════╤════════════════╕
│"t1" │"m" │"t2" │
╞════════════════╪═════════════════════╪════════════════╡
│{"name":"Team1"}│{"Date":"2022-05-11"}│{"name":"Team2"}│
├────────────────┼─────────────────────┼────────────────┤
│{"name":"Team2"}│{"Date":"2022-05-12"}│{"name":"Team3"}│
└────────────────┴─────────────────────┴────────────────┘
In order to understand this solution, you can read about the concept of cardinality.
Basically, since the number of options for the first MATCH
is two per each (:Match) (two teams, one match) the query will return two options per each (:Match). Since you want only one results per match, you can use collect
to group these two lines into one.
In other words, your query is saying get all options for this arrangement, meaning two per match. The query here is getting all options per match and then "group by" match, to create a list of teams per each match.
Upvotes: 1