database - Neo4j - Cypher - 包含父母和孩子的图片库系统
问题描述
我是具有 mysql 背景的 Neo4j 新手,我正在尝试将旧的 mysql 图像库系统转换为 Neo4j 图形数据库,我提供的架构如下图所示:
_ 有两个关系类型的用户节点:
- 发表:
(:User)-[:POSTED]->(:Post)
- 有头像:
(:User)-[:HAS_AVATAR]->(:Image)
_ 具有两种关系类型的帖子节点:
- 有子为父画廊帖子:
(:Post)-[:HAS_CHILD]->(:Post)
- 有画廊子帖子的图片:
(:Post)-[:HAS_IMAGE]->(:Image)
_ 最后的图像节点。
这是一个简化版本,实际上每个帖子(父母和孩子)都可以有链接或视频而不是图像,并且可以被用户评论或喜欢。
为了从图中获取我需要的所有数据,我使用了这个密码查询:
MATCH (p:Post)<-[:POSTED]-(u:User) WHERE NOT (p)<-[:HAS_CHILD]-(:Post)
MATCH (u)-[:HAS_AVATAR]->(ua:Image)
OPTIONAL MATCH (p)-[:HAS_CHILD]->(c:Post)
OPTIONAL MATCH (p)-[:HAS_IMAGE]-(i:Image)
OPTIONAL MATCH (c)-[:HAS_IMAGE]-(ci:Image)
RETURN
[p._id, [u.username, ua._id], i._id, c._id, ci._id] as post
它最终得到这样的结果:
再次,我保持这个查询简单,为了清楚起见,每个图像都有一个 id、一个宽度和一个高度,每个子帖子可以有与其父不同的用户,每个帖子都有自己的评论和来自不同的喜欢用户真正的结果是远远大于这个。
现在我必须处理很多lodash/union
,以摆脱所有重复的结果(帖子ID,用户名......)
我的问题是,我做得对吗?有更好的方法吗?我实际上正在阅读MERGE
并尝试实施它。
所以我指的是你们和你们的专业知识,特别是如果它可以在密码查询中获取所有联合函数。
谢谢。
解决方案
从评论来看,您似乎想使用聚合将结果收集在一起,并最大限度地减少结果中的行数和元素重复。
从您的查询来看,您可能已经尝试通过输出列表来执行此操作。请记住,将一些结果放入列表(仅更改每行结果的结构)与使用或其他进行聚合的方法之间存在差异collect()
,因为它从多行获取结果并将它们收集到一个行(每个分组键),因此最终总行数更少。
这是您的查询,其中包含为每个父帖子收集子帖子的更改:
MATCH (p:Post)<-[:POSTED]-(u:User)
WHERE NOT (p)<-[:HAS_CHILD]-()
// the above uses the degree of those relationships on the node, more efficient
OPTIONAL MATCH (p)-[:HAS_CHILD]->(c:Post) // potentially multiple children
OPTIONAL MATCH (c)-[:HAS_IMAGE]-(ci:Image) // assume at most 1 image per child post
WITH p, u, collect(c {._id, image:ci._id}) as children
OPTIONAL MATCH (p)-[:HAS_IMAGE]-(i:Image) // assume at most 1 image per post
WITH p, u, children, i
MATCH (u)-[:HAS_AVATAR]->(ua:Image) // assume at most 1 avatar per user
RETURN p {._id, image:i._id, children} as post, u {.username, avatar:ua._id} as user
这使用地图投影从地图中投影出属性(或者在这种情况下,从节点中投影出属性)并将我们自己的属性从其他匹配元素添加到地图中。
或者,如果你想做类似的事情,但除了收集每个用户的帖子,你可以这样做:
MATCH (p:Post)<-[:POSTED]-(u:User)
WHERE NOT (p)<-[:HAS_CHILD]-()
// the above uses the degree of those relationships on the node, more efficient
OPTIONAL MATCH (p)-[:HAS_CHILD]->(c:Post) // potentially multiple children
OPTIONAL MATCH (c)-[:HAS_IMAGE]-(ci:Image) // assume at most 1 image per child post
WITH u, p, collect(c {._id, image:ci._id}) as children
OPTIONAL MATCH (p)-[:HAS_IMAGE]-(i:Image) // assume at most 1 image per post
WITH u, collect(p {._id, image:i._id, children}) as posts
MATCH (u)-[:HAS_AVATAR]->(ua:Image) // assume at most 1 avatar per user
RETURN u {.username, avatar:ua._id} as user, posts
推荐阅读
- mysql - mysql错误:mysql_handledberror:成功
- laravel - 如何在 laravel 查询生成器中,为父表中的每条记录获取满足特定条件的子行数?
- jquery - 仅删除字符串
- monitoring - Grafana + Prometheus:显示事件发生频率的单一统计信息
- javascript - Javascript:如果 (x === 'foo' || 'bar') 在我使用 'bar' 时不会产生正确的陈述。为什么?
- mysql - 获取调用 MySQL 过程的对象名称
- jquery-plugins - 循环不是函数
- c# - 无法推断 Lambda 表达式类型参数
- nginx - Nginx 正则表达式所有路径都期望
- node.js - 将查询结果传递给外部变量