首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Neo4J (Cypher)按节点对多个关系进行分组

Neo4J (Cypher)按节点对多个关系进行分组
EN

Stack Overflow用户
提问于 2021-05-04 21:29:59
回答 1查看 36关注 0票数 0

我正在开发一个小型的推荐系统,为下一场比赛推荐玩家。推荐包括首先关注的玩家,然后是玩家之前玩过的玩家,按游戏数量排序。

结果将是Player, is_followed (true|false), GameIds

我有PlayerGame节点,它们的关系是Game -[:HAS_PLAYER]-> Player

Player节点与Player -[:FOLLOWS]-> Player直接相关。

我的测试DB:

代码语言:javascript
复制
CREATE (superman:Player {playerID: 'superman', name:'Superman', sanitizedName: 'superman'})
CREATE (batman:Player {playerID: 'batman', name:'Batman', sanitizedName: 'batman'})
CREATE (catwoman:Player {playerID: 'catwoman', name:'Catwoman', sanitizedName: 'catwoman'})
CREATE (lois:Player {playerID: 'lois', name:'Lois Lane', sanitizedName: 'lois lane'})
CREATE (wonderwoman:Player {playerID: 'wonderwoman', name:'Wonder Woman', sanitizedName: 'wonder woman'})
CREATE (aquaman:Player {playerID: 'aquaman', name:'Aquaman', sanitizedName: 'aquaman'})
CREATE (flash:Player {playerID: 'flash', name:'Flash', sanitizedName: 'flash'})
CREATE (cyborg:Player {playerID: 'cyborg', name:'Cyborg', sanitizedName: 'cyborg'})
CREATE (joker:Player {playerID: 'joker', name:'Joker', sanitizedName: 'joker'})
CREATE (lex:Player {playerID: 'lex', name:'Lex Luthor', sanitizedName: 'lex luthor'})
CREATE (green:Player {playerID: 'green', name:'Green Lantern', sanitizedName: 'green lantern'})

CREATE (g1:Game {gameId:"game-1"})
CREATE (g1)-[:HAS_PLAYERS {teamId:"0"}]->(superman)
CREATE (g1)-[:HAS_PLAYERS {teamId:"0"}]->(aquaman)
CREATE (g1)-[:HAS_PLAYERS {teamId:"1"}]->(batman)
CREATE (g1)-[:HAS_PLAYERS {teamId:"1"}]->(flash)

CREATE (g2:Game {gameId:"game-2"})
CREATE (g2)-[:HAS_PLAYERS {teamId:"0"}]->(superman)
CREATE (g2)-[:HAS_PLAYERS {teamId:"0"}]->(batman)
CREATE (g2)-[:HAS_PLAYERS {teamId:"1"}]->(joker)
CREATE (g2)-[:HAS_PLAYERS {teamId:"1"}]->(lex)

CREATE (g3:Game {gameId:"game-3"})
CREATE (g3)-[:HAS_PLAYERS {teamId:"0"}]->(flash)
CREATE (g3)-[:HAS_PLAYERS {teamId:"0"}]->(lois)
CREATE (g3)-[:HAS_PLAYERS {teamId:"1"}]->(wonderwoman)
CREATE (g3)-[:HAS_PLAYERS {teamId:"1"}]->(aquaman)

CREATE (g4:Game {gameId:"game-4"})
CREATE (g4)-[:HAS_PLAYERS {teamId:"0"}]->(joker)
CREATE (g4)-[:HAS_PLAYERS {teamId:"0"}]->(cyborg)
CREATE (g4)-[:HAS_PLAYERS {teamId:"1"}]->(wonderwoman)
CREATE (g4)-[:HAS_PLAYERS {teamId:"1"}]->(green)

CREATE (g5:Game {gameId:"game-5"})
CREATE (g5)-[:HAS_PLAYERS {teamId:"0"}]->(catwoman)
CREATE (g5)-[:HAS_PLAYERS {teamId:"1"}]->(green)

CREATE (batman)-[:FOLLOWS]->(superman)
CREATE (batman)-[:FOLLOWS]->(catwoman)

CREATE (lex)-[:FOLLOWS]->(joker)
CREATE (joker)-[:FOLLOWS]->(lex)
;

有了这些数据,我想向蝙蝠侠推荐他的下一场比赛的球员,结果必须是:

代码语言:javascript
复制
superman true  [game-1, game-2]
catwoman true  []
aquaman  false [game-1]
flash    false [game-1]
joker    false [game-2]
lex      false [game-2]

更新:我有下一个问题,但是下面的玩家不见了:

代码语言:javascript
复制
MATCH (u:Player{playerID:"batman"})
OPTIONAL MATCH (u)<-[:HAS_PLAYERS]-(g:Game)-[:HAS_PLAYERS]->(p:Player) 
RETURN p, EXISTS((u)-[:FOLLOWS]->(p)) AS is_followed, COUNT(g) AS num_games, collect(g) AS games
ORDER BY num_games DESC

谢谢!

更新2

这种方法可以更“可读性”,但性能比公认的答案差得多。

代码语言:javascript
复制
MATCH (u:Player{playerID:"batman"})
CALL {
    WITH u
    MATCH (u)<-[:HAS_PLAYERS]-(g:Game)-[:HAS_PLAYERS]->(p:Player) 
    RETURN p

    UNION

    WITH u
    MATCH (u)-[:FOLLOWS]->(p:Player)
    RETURN p
}
WITH p,
    EXISTS((u)-[:FOLLOWS]->(p)) AS is_followed,
    [(u)<-[:HAS_PLAYERS]-(g:Game)-[:HAS_PLAYERS]->(p) | g.gameId] AS games
RETURN p.name, is_followed, size(games) AS num_games, games
ORDER BY num_games DESC
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-05 01:27:38

你没有得到猫女,因为你只通过:游戏节点匹配:玩家与蝙蝠侠相关,你还需要匹配(u:玩家{playerID:“蝙蝠侠”})-:跟随->(p:玩家)

代码语言:javascript
复制
MATCH (u:Player{playerID:"batman"})
OPTIONAL MATCH (u)<-[:HAS_PLAYERS]-(g:Game)-[:HAS_PLAYERS]->(p:Player) 
RETURN p.playerID, EXISTS((u)-[:FOLLOWS]->(p)) AS is_followed, COUNT(g) AS num_games, collect(g.gameId) AS games
ORDER BY num_games DESC
union
match (u:Player{playerID:"batman"})-[:FOLLOWS]->(p:Player)
where not exists( (u)<-[:HAS_PLAYERS]-(:Game)-[:HAS_PLAYERS]->(p:Player) )
RETURN p.playerID, true AS is_followed, 0 AS num_games, [] AS games

(我想不出没有联合的方法,但这可能是可能的)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67385780

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档