2015-06-08 64 views
1

我很努力地编写一个查询,它会为每个用户返回关于大多数播放曲目的信息。 我去像这样的东西:Neo4J - 选择最大记录数

MATCH (l:Listener)-[lo:LOGS]->(s:Scrobble)-[f:FEATURES]->(t:Track)<-[p:PERFORMS]-(a:Artist) 
with l,a,count(*) as numberOfScrobbles 
return l.name, a.title, numberOfScrobbles 

,并得到值的列表:用户名 - 艺术家的名字 - 通过给艺术家创造与数百曲目的数量。

我的目标是为每个用户获取最受欢迎的艺术家(艺术家为每个用户提供大部分音乐作品)。我得到的最接近的是这个:

MATCH (l:Listener)-[lo:LOGS]->(s:Scrobble)-[f:FEATURES]->(t:Track)<-[p:PERFORMS]-(a:Artist) 
with l,a,count(*) as numberOfScrobbles 
return l.name, max(numberOfScrobbles) 

,给了我一个最喜爱的艺术家为特定用户播放的曲目的数量,但我怎么能加入适当的艺术家的名字,以这样的结果?

任何线索/提示?

回答

2

一个想法(也许还有一个更简单的解决方案):

MATCH (l:Listener)-[lo:LOGS]->(s:Scrobble)-[f:FEATURES]->(t:Track)<-[p:PERFORMS]-(a:Artist) 
with l,a,count(*) as numberOfScrobbles 
with l, collect(a) as artists, collect(numberOfScrobbles) as counts 
with l, artists, reduce(x=[0,0], idx in range(0,size(counts)-1) | case when counts[idx] > x[1] then [idx,counts[idx]] else x end)[0] as index 
return l.name, artists[index] 

reduce功能用于查找数组中的最大元素的位置。该索引然后用于标记artists数组。

+0

谢谢!解决了这个问题,但是使用了一些手工比较算法。我认为有一些内置功能可以增强这种操作(例如SQL中的子查询)。好吧,看起来Neo4J在查询数据存储时涉及更直接的编程;)。 – mcmajkel

1

这是一个查询,应该改善@ StefanAmbruster的正确答案。它使用MAX()函数来查找每个侦听器的最大numberOfScrobbles;提取所有为该听众取得最大数字的艺术家;然后返回每个聆听者,其获奖艺术家的集合以及最大数量。

MATCH (l:Listener)-[:LOGS]->(:Scrobble)-[:FEATURES]->(:Track)<-[:PERFORMS]-(a:Artist) 
WITH l, a, count(*) as numberOfScrobbles 
WITH l, collect(a) as artists, collect(numberOfScrobbles) as counts, MAX(numberOfScrobbles) AS max_nos 
WITH l, max_nos, extract(i IN range(0, size(counts)-1) | CASE WHEN counts[i] = max_nos THEN artists[i] ELSE NULL END) AS as 
RETURN l.name, as, max_nos;