计算所有节点neo4j之间的相似性 - 获得节点对的不同值

时间:2018-03-27 02:16:36

标签: neo4j

我的数据库中有两种节点:

  1. USER
  2. MEDIA
  3. 和一个关系 - “喜欢”

    两个节点之间的关系如下所述:

    (:USER) - [:LIKES] - GT;(:MEDIA)

    我正在尝试根据每个节点对之间共享的媒体数量计算所有“USER”节点之间的相似度(Jaccard Similarity)

    然后将该相似性存储为“ISSIMILAR”关系。 “ISSIMILAR”关系具有称为“相似性”的属性,其存储节点之间的相似性

    这是我的疑问:

    Match(u:User)
    
    WITH COLLECT(u) as users
    
    UNWIND users as user
    
    MATCH(user:User{id:user.id})-[:LIKES]->(common_media:Media)<-[:LIKES]-(other:User)
    
    WITH user,other,count(common_media) AS intersection, COLLECT(common_media.name) as i
    
    MATCH(user)-[:LIKES]->(user_media:Media)
    
    WITH user,other,intersection,i, COLLECT(user_media.name) AS s1
    
    MATCH(other)-[:LIKES]->(other_media:Media)
    
    WITH user,other,intersection,i,s1, COLLECT(other_media.name) AS s2
    
    WITH user,other,intersection,s1,s2
    
    WITH user,other,intersection,s1+filter(x IN s2 WHERE NOT x IN s1) AS union, s1,s2
    
    WITH ((1.0*intersection)/SIZE(union)) as jaccard,user,other
    
    MERGE(user)-[:ISSIMILAR{similarity:jaccard}]-(other)
    

    运行此查询,我有两个问题:

    1. 我希望一对节点之间只有一个“ISSIMILAR”关系。但它创造了两个。
    2. 此“ISSIMILAR”关系“相似”属性具有不同的值。值应该相同
    3. 以下是该问题的可视化:

      MATCH(user:User)-[r]-(o:User) return o,user,r limit 4
      

      enter image description here

      enter image description here

      提前致谢

1 个答案:

答案 0 :(得分:1)

出现两个相似关系的问题,因为您不排除先前构造的相似关系。你可以通过这样做来避免这种情况:

...
UNWIND users as user
  UNWIND users as other 
    WITH user, other WHERE ID(user) > ID(other)
    MATCH(user)-[:LIKES]->(common_media:Media)<-[:LIKES]-(other) 
...

最后的查询可以更清晰:

MATCH (u:User) WITH COLLECT(u) AS users
UNWIND users AS user
UNWIND users AS other

MATCH (user)-[:LIKES]->(common_media:Media)<-[:LIKES]-(other) WHERE ID(other) > ID(user)
WITH user, other, COLLECT(common_media) AS intersection

MATCH (user)-[:LIKES]->(user_media:Media)
WITH user, other, intersection, 
     COLLECT(user_media) AS s1

MATCH (other)-[:LIKES]->(other_media:Media)
WITH user,other,intersection, s1, 
     COLLECT(other_media) AS s2

RETURN user, other,
       (1.0 * SIZE(intersection)) / (SIZE(s1) + SIZE(s2) - SIZE(intersection)) AS jaccard

MERGE (user)-[:ISSIMILAR {similarity: jaccard}]->(other)