Cypher查询计算同一标签的两个neo4j节点之间的余弦分数

时间:2018-01-23 09:40:13

标签: neo4j cypher cosine-similarity

我正在尝试为特定用例编写Cypher查询,但我无法想出一个。

我有一个neo4j数据库。我用以下方式用节点和关系填充它。 (上下文:此数据库代表电子商务网站的查询和产品)

每个节点都有以下两个标签之一

  1. 查询
  2. 产品
  3. 仅存在从“查询”节点到“产品”节点的关系(表示在用户输入查询后单击该产品)。边缘有一个分数,表示总点击次数。

    我想定义一个分数来衡量任何两个查询节点之间的重叠。因此,对于每个查询节点,我定义一个向量,其总组件数等于产品总数。每个组件等于查询与该产品之间边缘的分数。

    我现在想要计算这两个向量之间角度的余弦。但我无法编写单个cypher查询,它返回每个查询的余弦分数,查询'对。

    我能想出的最好的是这个查询

    MATCH (q1:Query {search_term:'sunglasses'})-[e1:INTERACTION
    {event_type:'CLICK'}]->(p:Product)<-[e2:INTERACTION 
    {event_type:'CLICK'}]-(q2:Query) 
    WITH q1, q2, sqrt(sum(e1.score * e1.score)) as sq1, sqrt(sum(e2.score * 
    e2.score)) as sq2, sum(e1.score * e2.score) as overlap_score
    RETURN q1, q2, overlap_score/(sq1 * sq2) as cosine
    ORDER BY cosine DESC
    

    但是这个查询不计算向量之间角度的余弦值,因为在计算每个向量的长度时(上面查询中的sq1和sq2),它忽略了第二个查询具有0分量的那些组件。 / p>

    我知道这个问题需要一些描述,但我无法找到解决方案。任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:1)

如果您检查this graphgist,我们可以轻松窃取并修改您要查找的查询。

您的查询类似于:

MATCH (p1:Query {search_term:'sunglasses'})-[x:INTERACTION
{event_type:'CLICK'}]->(p:Product)<-[y:INTERACTION 
{event_type:'CLICK'}]-(p2:Query) 

WITH  SUM(x.score * y.score) AS xyDotProduct,
      SQRT(REDUCE(xDot = 0.0, a IN COLLECT(x.score) | xDot + a^2)) AS xLength,
      SQRT(REDUCE(yDot = 0.0, b IN COLLECT(y.score) | yDot + b^2)) AS yLength,
      p1, p2
MERGE (p1)-[s:SIMILARITY]-(p2)
SET   s.similarity = xyDotProduct / (xLength * yLength)

还可以查看APOC's documentation on cosine similarity