Cypher 查询遍历特定类型的所有节点并对相关节点进行分组
Cypher query to iterate through all nodes of a specific type and group related nodes
有人可以帮助neo4j新手(这是我第2天!)解决以下问题吗?
我有一个数据库,我有所有玩过游戏会话 (S) 的玩家 (P) 以及他们取得的分数。有无数个S,姑且称他们为S1, S2, S3 ...等等。还有无数个Ps, P1, P2, P3 ...等等
每个会话都有玩家,例如
(P)-[:播放]->(S)
每个会话的玩家数量不定,从 2 人到 10 人。
我想做的是访问每个会话,获取该会话的每个玩家,然后根据分数对他们进行排名。玩家需要先按分数排序,然后进行排名,每个分数高于前一个玩家的玩家具有BEAT关系。通常,我会使用 FOREACH 循环,但我不知道如何用 Cypher 做同样的事情。
例如,S1 有玩家 P1、P3 和 P5。如果 P3 得到 100,P1 得到 70,P5 得到 30,我想建立以下关系:
(P3)-[:BEAT]->(P1)-[:BEAT]->(P5)
我需要为每个会话执行此操作。解决此问题的最佳方法是什么?
此致,
假设 score
存储在 :PLAYED
关系上,这应该有效:
// Find all players who have played in a session
MATCH (p:Player)-[r:PLAYED]->(s:Session)
// for each Session, order the players by their score for that session
WITH s, p ORDER BY r.score DESC
// for each session, group the players (now ordered by their scores)
WITH s, COLLECT(p) AS players
// iterate over the sequence 0..number_of_players_in_this_session-2
UNWIND range(0,size(players)-2) AS i
// grab pairs of players, starting from the highest scoring
WITH players[i] AS l1, players[i+1] AS l2
// create :BEAT relationship
CREATE (l1)-[:BEAT]->(l2)
有一个简单的 Neo4j 控制台示例 here
当然这里存在数据建模问题,您没有将 :BEAT
关系与特定会话相关联。
只需添加一个节省几行 Cypher 的快捷方式,您可以安装 APOC Procedures 并使用 apoc.nodes.link()
快速创建您的关系链。
以 William Lyon 的查询为基础:
// Find all players who have played in a session
MATCH (p:Player)-[r:PLAYED]->(s:Session)
// for each Session, order the players by their score for that session
WITH s, p ORDER BY r.score DESC
// for each session, group the players (now ordered by their scores)
WITH s, COLLECT(p) AS players
CALL apoc.nodes.link(players, 'BEAT')
// can't end a query with CALL, so just do a dummy return of some kind
RETURN DISTINCT true
如果有人发现这个 post 有用,我想补充一点,要处理一个大的结果集(避免 运行 内存不足),试试这个:
// Find all players who have played in a session
MATCH (p:Player)-[r:PLAYED]->(s:Session)
// for each Session, order the players by their score for that session
WITH s, p ORDER BY r.score DESC
//Paginate/batch process results to avoid exhausting memory
SKIP 500000*n
LIMIT 500000
// for each session, group the players (now ordered by their scores)
WITH s, COLLECT(p) AS players
CALL apoc.nodes.link(players, 'BEAT')
// can't end a query with CALL, so just do a dummy return of some kind
RETURN DISTINCT true
即行
SKIP 500000*n
LIMIT 500000
已添加。设n = 0,不断递增,直到没有记录更新。
感谢所有为此主题做出贡献的人。
有人可以帮助neo4j新手(这是我第2天!)解决以下问题吗?
我有一个数据库,我有所有玩过游戏会话 (S) 的玩家 (P) 以及他们取得的分数。有无数个S,姑且称他们为S1, S2, S3 ...等等。还有无数个Ps, P1, P2, P3 ...等等
每个会话都有玩家,例如
(P)-[:播放]->(S)
每个会话的玩家数量不定,从 2 人到 10 人。
我想做的是访问每个会话,获取该会话的每个玩家,然后根据分数对他们进行排名。玩家需要先按分数排序,然后进行排名,每个分数高于前一个玩家的玩家具有BEAT关系。通常,我会使用 FOREACH 循环,但我不知道如何用 Cypher 做同样的事情。
例如,S1 有玩家 P1、P3 和 P5。如果 P3 得到 100,P1 得到 70,P5 得到 30,我想建立以下关系:
(P3)-[:BEAT]->(P1)-[:BEAT]->(P5)
我需要为每个会话执行此操作。解决此问题的最佳方法是什么?
此致,
假设 score
存储在 :PLAYED
关系上,这应该有效:
// Find all players who have played in a session
MATCH (p:Player)-[r:PLAYED]->(s:Session)
// for each Session, order the players by their score for that session
WITH s, p ORDER BY r.score DESC
// for each session, group the players (now ordered by their scores)
WITH s, COLLECT(p) AS players
// iterate over the sequence 0..number_of_players_in_this_session-2
UNWIND range(0,size(players)-2) AS i
// grab pairs of players, starting from the highest scoring
WITH players[i] AS l1, players[i+1] AS l2
// create :BEAT relationship
CREATE (l1)-[:BEAT]->(l2)
有一个简单的 Neo4j 控制台示例 here
当然这里存在数据建模问题,您没有将 :BEAT
关系与特定会话相关联。
只需添加一个节省几行 Cypher 的快捷方式,您可以安装 APOC Procedures 并使用 apoc.nodes.link()
快速创建您的关系链。
以 William Lyon 的查询为基础:
// Find all players who have played in a session
MATCH (p:Player)-[r:PLAYED]->(s:Session)
// for each Session, order the players by their score for that session
WITH s, p ORDER BY r.score DESC
// for each session, group the players (now ordered by their scores)
WITH s, COLLECT(p) AS players
CALL apoc.nodes.link(players, 'BEAT')
// can't end a query with CALL, so just do a dummy return of some kind
RETURN DISTINCT true
如果有人发现这个 post 有用,我想补充一点,要处理一个大的结果集(避免 运行 内存不足),试试这个:
// Find all players who have played in a session
MATCH (p:Player)-[r:PLAYED]->(s:Session)
// for each Session, order the players by their score for that session
WITH s, p ORDER BY r.score DESC
//Paginate/batch process results to avoid exhausting memory
SKIP 500000*n
LIMIT 500000
// for each session, group the players (now ordered by their scores)
WITH s, COLLECT(p) AS players
CALL apoc.nodes.link(players, 'BEAT')
// can't end a query with CALL, so just do a dummy return of some kind
RETURN DISTINCT true
即行
SKIP 500000*n
LIMIT 500000
已添加。设n = 0,不断递增,直到没有记录更新。
感谢所有为此主题做出贡献的人。