Neo4j - 如何为我的图形构建正确的多维查询

时间:2015-04-01 02:26:26

标签: graph neo4j cypher

我有一个像用户,朋友,评论,喜欢等图形的简单社交网络。用户可以拥有"项目,评论"项目",喜欢"项目"。我正在尝试编写一个返回"项目"的cypher查询。沿着w /额外信息在我的流中显示它们。

我尝试过使用可选匹配收集等内容,但总有一部分结果不起作用。

具体来说,对于给定的用户(比如user1),我想要返回" items"的是:

  1. 特定用户+他的朋友拥有
  2. 显示喜欢的数量,
  3. 还会显示评论数量,
  4. 知道该项目是否已由我拥有(因此我可以隐藏"在UI中拥有"按钮)
  5. 如果该项目归朋友所有,我想显示最多2位朋友的姓名,图片(但如果5位朋友拥有该项目,则不超过2位朋友)
  6. 您可以在下面复制粘贴以获取图表

    // 3 users
    CREATE (u1:USER{name:"USER1", image: "image1"})
    CREATE (u2:USER{name:"USER2", image: "image2"})
    CREATE (u3:USER{name:"USER3", image: "image3"})
    
    //3 items
    CREATE (i1:ITEM{name:"ITEM1"})
    CREATE (i2:ITEM{name:"ITEM2"})
    CREATE (i3:ITEM{name:"ITEM3"})
    
    
    // OWNERSHIP ..
    
    //user1 owns 2 items
    CREATE (u1)-[:OWNS]->(i1)
    CREATE (u1)-[:OWNS]->(i2)
    
    
    // user2 owns i2 and i3 
    CREATE (u2)-[:OWNS]->(i2)
    CREATE (u2)-[:OWNS]->(i3)
    
    // user3 also owns i2 and i3 (so i2 is owned by u1, u2 and u3; and i3 is owned by u2 and u3)
    CREATE (u3)-[:OWNS]->(i2)
    CREATE (u3)-[:OWNS]->(i3)     
    
    // FRIENDSHIP..
    
    // user1 is friend of both user2 and user3
    CREATE (u1)-[:FRIEND_OF]->(u2)
    CREATE (u1)-[:FRIEND_OF]->(u3)
    
    
    // COMMENTS ..
    
    //user1 has commented on all those items he owns
    CREATE (u1i1:COMMENT{text:"user1 comment on item1"})
    CREATE (u1)-[:COMMENTED]->(u1i1)-[:COMMENT_FOR]->(i1)
    
    CREATE (u1i2:COMMENT{text:"user1 comment on item2"})
    CREATE (u1)-[:COMMENTED]->(u1i2)-[:COMMENT_FOR]->(i2)
    
    //user 2 has also commented on all those he owns
    CREATE (u2i2:COMMENT{text:"user2 comment on item2"})
    CREATE (u2)-[:COMMENTED]->(u2i2)-[:COMMENT_FOR]->(i2)
    
    CREATE (u2i3:COMMENT{text:"user2 comment on item3"})
    CREATE (u2)-[:COMMENTED]->(u2i3)-[:COMMENT_FOR]->(i3)
    
    
    // LIKES ..
    
    //user1 has liked user2's and user3's items
    CREATE (u1)-[:LIKED]->(i2)
    CREATE (u1)-[:LIKED]->(i3)
    
    //user2 has liked user1's items
    CREATE (u2)-[:LIKED]->(i1)
    

2 个答案:

答案 0 :(得分:4)

让我们逐步构建您的查询:

具体来说,对于给定的用户(比如user1),我想返回“items”: 特定用户+他的朋友拥有

MATCH (u:USER {name: "USER1"})-[:FRIEND_OF*0..1]-(friend:USER)-[:OWNS]-(i:ITEM)
WITH u,i, 
     // Know if the item is already owned by me (so I can hide "own" button in the UI) 
     sum(size((u)-[:OWNS]->(i))) > 0 as user_owns,
     // If the item is owned by friends, I want to show name, image of up to 2 friends 
     collect({name:friend.name, image:friend.image})[0..2] as friends

RETURN u,i, user_owns, friends
// show number of likes,
       sum(size(()-[:LIKED]->(i))) as like,
// also show number of comments,
       sum(size(()-[:COMMENT_FOR]->(i))) as comments

实际上因为这是一个很好的问题,我坐下来创建了一个GraphGist documenting each step here

答案 1 :(得分:3)

相当容易。首先,您需要在FRIEND_OF上从0..1获得可变路径长度匹配,并自行返回。关注那些拥有的所有物品。

使用OPTIONAL MATCH作为喜欢和评论,因为可能存在或可能不存在。

由于单个项目可能有多条路径,因此您需要计算不同的赞和评论。

要检查您是否已拥有该项目,请检查上面的变量路径匹配的端点(如果其名称是您的。)

为了获取拥有该项目的朋友的两张图片,过滤您朋友的列表并返回image属性。最后一步是使用下标运算符对前两个元素进行切片。

MATCH (:USER { name:'USER1' })-[:FRIEND_OF*0..1]->(me_or_friend)-[:OWNS]->(item)
OPTIONAL MATCH (item)<-[l:LIKED]-()
OPTIONAL MATCH (item)<-[c:COMMENT_FOR]-()
WITH item, count(distinct l) AS likes, count(distinct c) AS comments, 
    collect(DISTINCT me_or_friend) AS me_or_friends
RETURN item, likes, comments, 
    ANY (x IN me_or_friends WHERE x.name='USER1') AS i_already_own,
    [x IN me_or_friends  WHERE x.name<>'USER1' | x.image][0..2] as friendImages

最终评论:

如果您在问题中显示您已经尝试过自己尝试解决问题,我们将非常感激。像“为我解决问题”这样的问题并不是那么受欢迎。