(n)->(on)<-(n) 密码查询给了我一个笛卡尔积
(n)->(on)<-(n) cypher query gives me a cartesian product
我有一个类似这样的 Cypher 查询:
MATCH (t1:Team)-[:PLAYS_ON]->(m:Match)<-[:PLAYS_ON]-(t2:Team)
RETURN t1 AS "Team 1", m AS "Match", t2 as "Team 2"
我的目标是创建一个查询,让我可以查看匹配项以及哪些团队在相互匹配的情况下相互匹配。
假设第 1 队、第 2 队和第 3 队,比赛是第 1 队对第 2 队和第 2 队对第 3 队,我的预期输出是:
+------+-----+------+
|Team 1|match|Team 2|
|------+-----+------|
|Team 1|date |Team 2|
|Team 2|date |Team 3|
+------+-----+------+
但我得到:
+------+-----+------+
|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|
+------+-----+------+
我对 Cypher/Neo4J 比较陌生,所以,如果事实证明我犯了一个非常明显和愚蠢的错误,我不会留下深刻的印象,但我没有大脑看到它.
感谢您的回答!
一种方法是:
MATCH (t:Team)-[:PLAYS_ON]->(m:Match)
WITH collect(t) AS t, m
RETURN t[0] AS t1, m, t[1] AS t2
此示例数据中的哪个:
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)
会给你这个:
╒════════════════╤═════════════════════╤════════════════╕
│"t1" │"m" │"t2" │
╞════════════════╪═════════════════════╪════════════════╡
│{"name":"Team1"}│{"Date":"2022-05-11"}│{"name":"Team2"}│
├────────────────┼─────────────────────┼────────────────┤
│{"name":"Team2"}│{"Date":"2022-05-12"}│{"name":"Team3"}│
└────────────────┴─────────────────────┴────────────────┘
为了理解这个解决方案,您可以阅读cardinality的概念。
基本上,由于第一个 MATCH
的选项数量是每个 (:Match) 两个(两队,一场比赛),查询将 return 每个 (:Match) 两个选项).由于每次匹配只需要一个结果,因此可以使用 collect
将这两行组合为一行。
换句话说,您的查询是说获取此排列的所有选项,这意味着每个匹配项有两个。此处的查询是获取每场比赛的所有选项,然后“分组依据”比赛,以创建每场比赛的球队列表。
另一种实现你想要的方法是这个查询(使用 Nimrod Serok 的图表):
MATCH (t1:Team)-[:PLAYS_ON]->(m:Match)<-[:PLAYS_ON]-(t2:Team)
WHERE id(t1) < id(t2)
RETURN t1, m, t2
之所以有效,是因为 WHERE
子句确保不会在两个方向上考虑相同的团队配对(这会导致笛卡尔积)。
我有一个类似这样的 Cypher 查询:
MATCH (t1:Team)-[:PLAYS_ON]->(m:Match)<-[:PLAYS_ON]-(t2:Team)
RETURN t1 AS "Team 1", m AS "Match", t2 as "Team 2"
我的目标是创建一个查询,让我可以查看匹配项以及哪些团队在相互匹配的情况下相互匹配。
假设第 1 队、第 2 队和第 3 队,比赛是第 1 队对第 2 队和第 2 队对第 3 队,我的预期输出是:
+------+-----+------+
|Team 1|match|Team 2|
|------+-----+------|
|Team 1|date |Team 2|
|Team 2|date |Team 3|
+------+-----+------+
但我得到:
+------+-----+------+
|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|
+------+-----+------+
我对 Cypher/Neo4J 比较陌生,所以,如果事实证明我犯了一个非常明显和愚蠢的错误,我不会留下深刻的印象,但我没有大脑看到它.
感谢您的回答!
一种方法是:
MATCH (t:Team)-[:PLAYS_ON]->(m:Match)
WITH collect(t) AS t, m
RETURN t[0] AS t1, m, t[1] AS t2
此示例数据中的哪个:
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)
会给你这个:
╒════════════════╤═════════════════════╤════════════════╕
│"t1" │"m" │"t2" │
╞════════════════╪═════════════════════╪════════════════╡
│{"name":"Team1"}│{"Date":"2022-05-11"}│{"name":"Team2"}│
├────────────────┼─────────────────────┼────────────────┤
│{"name":"Team2"}│{"Date":"2022-05-12"}│{"name":"Team3"}│
└────────────────┴─────────────────────┴────────────────┘
为了理解这个解决方案,您可以阅读cardinality的概念。
基本上,由于第一个 MATCH
的选项数量是每个 (:Match) 两个(两队,一场比赛),查询将 return 每个 (:Match) 两个选项).由于每次匹配只需要一个结果,因此可以使用 collect
将这两行组合为一行。
换句话说,您的查询是说获取此排列的所有选项,这意味着每个匹配项有两个。此处的查询是获取每场比赛的所有选项,然后“分组依据”比赛,以创建每场比赛的球队列表。
另一种实现你想要的方法是这个查询(使用 Nimrod Serok 的图表):
MATCH (t1:Team)-[:PLAYS_ON]->(m:Match)<-[:PLAYS_ON]-(t2:Team)
WHERE id(t1) < id(t2)
RETURN t1, m, t2
之所以有效,是因为 WHERE
子句确保不会在两个方向上考虑相同的团队配对(这会导致笛卡尔积)。