如何计算Neo4j中的排名

时间:2015-04-14 06:23:04

标签: neo4j

enter image description here

我有两种类型的节点(游戏和播放器)和一种关系(PLAYED)。 PLAYED 关系正在拥有一个属性'积分' 示例数据:
球员(309274)得到10分 球员(309275)得到20分 球员(309276)得分30分 球员(309277)得到40分 球员(309278)得分50分
我想计算一个玩家等级 309278,即来自密码查询的5。有人可以帮我在这里生成密码查询吗?

3 个答案:

答案 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排名计算的人有所帮助!