Neo4j - 如何为我的图表构建适当的多维查询

Neo4j - How to build proper multi-dimensional query for my graph

我有一个简单的社交网络,例如带有用户、朋友、评论、喜欢等的图表。用户可以 "own" 项,对 "items" 发表评论,喜欢 "items"。我正在尝试编写一个密码查询 returns "items" 以及额外的信息以在我的流中显示它们。

我试过使用optional matchcollect之类的东西,但总有一部分结果不起作用.

具体来说,对于给定的用户(比如 user1),我想 return "items" 即:

  1. 特定用户 + 他的朋友拥有
  2. 显示点赞数,
  3. 还显示评论数,
  4. 知道该项目是否已归我所有(这样我就可以隐藏 UI 中的 "own" 按钮)
  5. 如果该物品为朋友所有,我想显示最多 2 个朋友的姓名和图片(但如果 5 个朋友拥有该物品,则不超过 2 个朋友)

您可以在下面复制粘贴以获取图表

// 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)

相当容易。首先,您需要自己在 FRIEND_OF return 上有一个从 0..1 开始的可变路径长度匹配。关注那些人拥有的所有物品。

使用 OPTIONAL MATCH 点赞和评论,因为可能存在也可能不存在。

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

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

要获取最多两张拥有该项目的朋友的图像,请筛选您的朋友列表和 return 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

最终评论:

如果您在问题中展示您已经尝试解决问题的方法,我们将不胜感激。 "solve that problem for me" 之类的问题不太受欢迎。

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

具体来说,对于给定的用户(比如 user1),我想 return "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