我有两种类型的节点(游戏和播放器)和一种关系(PLAYED)。
PLAYED 关系正在拥有一个属性'积分'
示例数据:
球员(309274)得到10分
球员(309275)得到20分
球员(309276)得分30分
球员(309277)得到40分
球员(309278)得分50分
我想计算一个玩家等级 309278,即来自密码查询的5。有人可以帮我在这里生成密码查询吗?
答案 0 :(得分:5)
MATCH (p:Player)-[pl:PLAYED]->(:Game {id:{game-id}})
RETURN p.name
ORDER BY pl.score desc
然后行号是您的排名,您的客户可以轻松计算
访问某个等级:
MATCH (p:Player)-[pl:PLAYED]->(:Game {id:{game-id}})
RETURN p.name
ORDER BY pl.score desc
SKIP 4 LIMIT 1
计算等级,你可能会做这样的事情(效率不高):
MATCH (p:Player)-[pl:PLAYED]->(:Game {id:{game-id}})
WITH p,pl
ORDER BY pl.score desc
// create a a collection
WITH collect(p) as players
UNWIND reduce(acc=[],idx in range(0,size(players)-1) |
acc + [idx+1,players[idx]]) as player_rank
RETURN player_rank
答案 1 :(得分:1)
基于Michael Hunger's answer,以下查询计算排名并将玩家及其排名返回到同一行而不是交替行:
MATCH (p:Player)-[pl:PLAYED]->(:Game {id:{game-id}})
WITH p, pl
ORDER BY pl.score desc
WITH collect(p) as players
MATCH (p2:Player)-[pl2:PLAYED]->(:Game {id:{game-id}})
RETURN p2, size(filter(x in players where pl2.score < x.score)) + 1
它的工作方式是按照他们的分数对球员进行排序,然后 - 对于每个球员p2
- 它计算得分更高的球员数量,等于p2
的0为基础秩。
需要注意的是,如果玩家数量很大,那么O(n²)的复杂度就会非常低效。优点是它允许进一步处理与玩家有关的等级,例如,将他们的等级存储在关系中:
SET pl2.rank = 1 + size(filter(x in players where pl2.score < x.score))
可以在以后查询,无需进一步计算:
MATCH (p:Player)-[pl:PLAYED]->(:Game {id:{game-id}})
RETURN pl.rank
答案 2 :(得分:0)
几年后我要回答,是因为我发现自己需要类似的查询,并使用了出色的APOC
插件apoc.coll.indexOf
中的功能之一来解决了这个问题。
MATCH (p:Player)-[pl:PLAYED]->(g:Game)
WITH p, pl.score AS score
ORDER BY score DESC
WITH collect(p) AS players
UNWIND players AS player
RETURN player, apoc.coll.indexOf(players, player) + 1 AS rank // zero-indexed
;
如果集合很大,则可以将LIMIT N
附加到查询的末尾,以仅获得顶部的N
。我只是在大约17.2万个节点上运行了该查询,并且只用了3分钟多的时间就运行了(在运行MacOS版本10.14.6、3.1 GHz i7和16GB RAM的MacBook上使用Neo4j 3.5.7和APOC 3.5.0.4 );显然是YMMV。
我希望这对寻求Neo4j排名计算的人有所帮助!