Neo4j实时推荐性能

问题描述

我试图了解neo4j在实时推荐系统中的性能

以下是一个密码查询(从其沙箱中获取),该查询计算出与查询用户“辛西娅·弗里曼”最接近的前100名用户(按余弦距离):

MATCH 
    (p1:User {name: "Cynthia Freeman"})-[x:RATED]->(m:Movie)<-[y:RATED]-(p2:User)
WITH 
    COUNT(m) AS numberMovies,SUM(x.rating * y.rating) AS xyDotProduct,SQRT(REDUCE(xDot = 0.0,a IN COLLECT(x.rating) | xDot + a^2)) AS xLength,SQRT(REDUCE(yDot = 0.0,b IN COLLECT(y.rating) | yDot + b^2)) AS yLength,p1,p2 
WHERE
    numberMovies > 10
RETURN 
    p1.name,p2.name,xyDotProduct / (xLength * yLength) AS sim
ORDER BY sim DESC
LIMIT 100;

如果我的理解是正确的,则LIMIT子句后面就没有 magic ,因为与其他所有用户相比,距离计算仍然需要完成,因此可以实际解决查询,除非neo4j在幕后做某事,否则时间似乎有点长。

在另一个示例中,他们预先计算了用户节点之间的[:SIMILARITY]关系并将其存储在图中,因此查询前N个最相似的用户将成为节点的排序。这将直观地使图变得密集,因此与仅使用它们之间的相似性矩阵相比,没有任何存储优势。

我是否缺少有关图数据库(尤其是neo4j)工作方式的基本知识?如何将其扩展到实时应用程序中,在该应用程序中可以有成千上万的用户以及与之交互的更多产品?

解决方法

如果您想在成千上万个节点上使用某种余弦距离度量进行实时建议,最好将预先计算的值存储为关系。

关于使图密集,您可以将SIMILAR关系限制为前K个相似节点,还可以定义相似性截止阈值,这可以使您的图尽可能稀疏。您只能存储相关结果。因此,例如,在一个具有1万个节点的图形中,如果每个项目都与前10个其他节点具有连接,则这并不是一个真正的密集图形。如果您还删除从一个节点指向另一个节点并指向另一个节点的重复关系,则可以删除更多的关系。因此,如果可能的关系为10k * 10k(如果将关系视为无向,则除以2),则将不会有十亿个可能的关系,但最多只有10万个关系。

Graph Data Science library支持两种计算余弦距离的算法:

first naive version计算所有线对之间的距离,并可以使用topKsimilarityCutoff参数进行调整。

最近,在GDS 1.4预发行版中添加了kNN算法的optimized implementation。它使用本文所述的实现:https://dl.acm.org/doi/abs/10.1145/1963405.1963487

但是,要实时计算10k +个节点之间的相似度,可能仍需要花费100毫秒以上的时间才能使实时响应达到最大,因此采用预先计算的相似度关系才有意义。

,

除了@TomažBratanič的出色建议之外,还可以使您现有的查询更高效。它正在为每个p1/p2对执行数学计算,即使是后来由于共享电影的数量不超过10个而被过滤掉的对也是如此。相反,您应该尝试过滤掉不需要的p1/p2在进行计算之前。

例如:

MATCH
    (p1:User {name: "Cynthia Freeman"})-[x:RATED]->(m:Movie)<-[y:RATED]-(p2:User)
WITH
    COLLECT({xr: x.rating,yr: y.rating}) AS data
    p1,p2
WHERE
    SIZE(data) > 10
WITH
    REDUCE(s = 0,d IN data | s + d.xr * d.yr) AS xyDotProduct,SQRT(REDUCE(xDot = 0.0,a IN data | xDot + a.xr^2)) AS xLength,SQRT(REDUCE(yDot = 0.0,b IN data | yDot + b.yr^2)) AS yLength,p1,p2
RETURN 
    p1.name,p2.name,xyDotProduct / (xLength * yLength) AS sim
ORDER BY sim DESC
LIMIT 100;

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...