Neo4j - 如何为我的图表构建适当的多维查询
Neo4j - How to build proper multi-dimensional query for my graph
我有一个简单的社交网络,例如带有用户、朋友、评论、喜欢等的图表。用户可以 "own" 项,对 "items" 发表评论,喜欢 "items"。我正在尝试编写一个密码查询 returns "items" 以及额外的信息以在我的流中显示它们。
我试过使用optional match和collect之类的东西,但总有一部分结果不起作用.
具体来说,对于给定的用户(比如 user1),我想 return "items" 即:
- 特定用户 + 他的朋友拥有
- 显示点赞数,
- 还显示评论数,
- 知道该项目是否已归我所有(这样我就可以隐藏 UI 中的 "own" 按钮)
- 如果该物品为朋友所有,我想显示最多 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。
我有一个简单的社交网络,例如带有用户、朋友、评论、喜欢等的图表。用户可以 "own" 项,对 "items" 发表评论,喜欢 "items"。我正在尝试编写一个密码查询 returns "items" 以及额外的信息以在我的流中显示它们。
我试过使用optional match和collect之类的东西,但总有一部分结果不起作用.
具体来说,对于给定的用户(比如 user1),我想 return "items" 即:
- 特定用户 + 他的朋友拥有
- 显示点赞数,
- 还显示评论数,
- 知道该项目是否已归我所有(这样我就可以隐藏 UI 中的 "own" 按钮)
- 如果该物品为朋友所有,我想显示最多 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。