所以,我试图建立一个基本的推荐系统,我首先得到喜欢这部电影的人也喜欢(协作filtring)(基于用户),然后我得到一大堆各种数据(电影),因为我们说喜欢玩具故事的人也可能喜欢SCI-fi电影。但这种类型的电影与玩具故事无关,所以我想通过其类型再次过滤结果,玩具故事有5种类型(动画,动作,冒险等)我想只获得分享这些类型的电影共同的。
这是我的密码查询
match (x)<-[:HAS_GENRE]-(ee:Movie{id:1})<-[:RATED{rating: 5}]
-(usr)-[:RATED{rating: 5}]->(another_movie)<-[:LINK]-(l2:Link),
(another_movie)-[:HAS_GENRE]->(y:Genre)
WHERE ALL (m IN x.name WHERE m IN y.name)
return distinct y.name, another_movie, l2.tmdbId limit 200
我回来的第一张唱片是1977年的星球大战,其中只有冒险类型匹配玩具故事类型..帮助我写出更好的密码
答案 0 :(得分:1)
我们可以采取一些措施来改进查询。
收集类型应该允许以后正确的WHERE ALL子句。我们也可以暂停与推荐电影的链接节点的匹配,直到我们过滤到我们想要返回的电影。
试试这个:
MATCH (x)<-[:HAS_GENRE]-(ee:Movie{id:1})
// collect genres so only one result row so far
WITH ee, COLLECT(x) as genres
MATCH (ee)<-[:RATED{rating: 5}]-()-[:RATED{rating: 5}]->(another_movie)
WITH genres, DISTINCT another_movie
// don't match on genre until previous query filters results on rating
MATCH (another_movie)-[:HAS_GENRE]->(y:Genre)
WITH genres, another_movie, COLLECT(y) as gs
WHERE size(genres) <= size(gs) AND ALL (genre IN genres WHERE genre IN gs)
WITH another_movie limit 200
// only after we limit results should we match to the link
MATCH (another_movie)<-[:LINK]-(l2:Link)
RETURN another_movie, l2.tmdbId
由于电影可能会有很多评级,因此找到评分为5的电影的匹配将成为查询中最昂贵的部分。如果您的许多查询依赖于5的评级,那么每当用户将电影评级为5时,您可能需要考虑创建单独的[:MAX_RATED]关系,并将这些[:MAX_RATED]关系用于这些查询。这样可以确保您最初不会与大量评级的电影相匹配,这些电影都必须按照评级值进行过滤。
或者,如果您想考虑基于电影平均评分的推荐,您可能需要考虑缓存每部电影的所有评级的计算平均值(可能每天几次重新运行所有电影的计算)。如果您在电影节点上的平均评级属性上添加索引,则应该为评分相似的电影提供更快的匹配。