将 n 个节点连接到单个节点的最佳方法?
Best way to connect n nodes to a single node?
我正在为我当前正在构建的应用程序建模图表,其中我有 n 个用户连接到 n 个用户,我还有 n Posts 可以被 n 个用户赞。所以结构看起来像这样,对于给定的用户,
如果一个用户喜欢100个Post个节点,它会为该节点生成100条边(realtionships),当post为n时,边也为n。
所以一个用户将连接到 n 个用户和 n posts 和 n 个未来的节点类型。
因此使用中间节点从而减少给定节点的边,看起来像这样,
其中用户有一个名为 Collection 的中间节点,它将连接到喜欢,因为这是一个 属性 图,我可以向中间节点添加一个 属性 并使其行为就像连接来自用户(类似于 Likes.username = User.username)
这将类似于这个问题 (Graph database modelling: Should i use a collection node to avoid to many rel on a node)
我的想法是
这种中间连接节点的方式可以将垃圾与主节点隔离,从而可以加快自定义算法。
我的问题,
- 最好的扩展解决方案是什么?
- 为什么我应该考虑这个解决方案而不是另一个?
这个解决方案有利也有弊。
主要缺点是遍历操作会更昂贵,即。在找到帖子之前,您还需要遍历一个节点。
优点如下:
- 添加新 "likes" 时用户节点上的争用较少,即。 User @version 不会递增,因此您将能够并发地对 User 进行更新,而不会出现版本冲突
- 向 "likes" 节点添加信息的能力。您也可以单独使用边来执行此操作,但您必须复制所有边上的信息。
- 一个较小的用户,特别是低于 embedded/tree ridbag 阈值 http://orientdb.com/docs/2.2.x/RidBag.html 只要考虑使用二进制协议,当你有一个树 RidBag 时,它不会立即序列化到客户端,但是你会有一个迭代器,所以获取单个用户的开销不会很大。另一方面,使用 HTTP 协议,您将收到带有顶点的所有边 RID,因此在这种情况下,您将使用第二种方法节省大量带宽和计算时间。
关于您的问题,最好的解决方案是更适合您的工作负载的解决方案:如果您对 User 进行大量更新,则第二种解决方案会给您带来立竿见影的优势;如果你经常单独获取用户,第二种解决方案也会有优势;另一方面,如果您主要关心的是快速遍历,则第二种解决方案将不太合适。
根据非常好的书 Learning Neo4j(Rik Van Bruggen 着,可用于 download in the Neo4j's web site),您的问题称为 "Dense node" 或 "Supernode":连接过多的节点。
还是按照书上说的,超级节点
"becomes a real problem for graph traversals because the graph
database management system will have to evaluate all of the connected
relationships to that node in order to determine what the next step
will be in the graph traversal."
Rik 提出的解决方案非常接近您的解决方案(添加一个中间节点):它包括在用户和您喜欢的帖子之间添加一个 "meta" 节点。这个元节点最多应该有一百个连接。如果当前元节点达到 100 个连接,则必须创建一个新的元节点并将其添加到层次结构中,如图所示,以流行艺术家和您的粉丝为例:
Neo4j 团队一直在努力提高超级节点的性能,如 this Github commit(例如)所示,它改变了节点关系在磁盘上的存储方式,以一种链表结构。
我认为最好的办法是一开始就让你的图形模型尽可能简单。您(还)没有密集节点问题,过早的优化可能会给您的模型增加一些不必要的复杂性。如果将来密集节点成为问题,您可以更准确地更改模型。一开始,简单是个不错的选择。
您可以在这些链接中阅读更多关于图形数据库中超级节点的信息:
- Neo4j super node issue - fanning out pattern
- Dealing with supernodes in ArangoDB
- MATCHing Paths with Very Dense Nodes in Neo4j 2.2
我正在为我当前正在构建的应用程序建模图表,其中我有 n 个用户连接到 n 个用户,我还有 n Posts 可以被 n 个用户赞。所以结构看起来像这样,对于给定的用户,
如果一个用户喜欢100个Post个节点,它会为该节点生成100条边(realtionships),当post为n时,边也为n。 所以一个用户将连接到 n 个用户和 n posts 和 n 个未来的节点类型。
因此使用中间节点从而减少给定节点的边,看起来像这样,
其中用户有一个名为 Collection 的中间节点,它将连接到喜欢,因为这是一个 属性 图,我可以向中间节点添加一个 属性 并使其行为就像连接来自用户(类似于 Likes.username = User.username)
这将类似于这个问题 (Graph database modelling: Should i use a collection node to avoid to many rel on a node)
我的想法是
这种中间连接节点的方式可以将垃圾与主节点隔离,从而可以加快自定义算法。
我的问题,
- 最好的扩展解决方案是什么?
- 为什么我应该考虑这个解决方案而不是另一个?
这个解决方案有利也有弊。
主要缺点是遍历操作会更昂贵,即。在找到帖子之前,您还需要遍历一个节点。
优点如下:
- 添加新 "likes" 时用户节点上的争用较少,即。 User @version 不会递增,因此您将能够并发地对 User 进行更新,而不会出现版本冲突
- 向 "likes" 节点添加信息的能力。您也可以单独使用边来执行此操作,但您必须复制所有边上的信息。
- 一个较小的用户,特别是低于 embedded/tree ridbag 阈值 http://orientdb.com/docs/2.2.x/RidBag.html 只要考虑使用二进制协议,当你有一个树 RidBag 时,它不会立即序列化到客户端,但是你会有一个迭代器,所以获取单个用户的开销不会很大。另一方面,使用 HTTP 协议,您将收到带有顶点的所有边 RID,因此在这种情况下,您将使用第二种方法节省大量带宽和计算时间。
关于您的问题,最好的解决方案是更适合您的工作负载的解决方案:如果您对 User 进行大量更新,则第二种解决方案会给您带来立竿见影的优势;如果你经常单独获取用户,第二种解决方案也会有优势;另一方面,如果您主要关心的是快速遍历,则第二种解决方案将不太合适。
根据非常好的书 Learning Neo4j(Rik Van Bruggen 着,可用于 download in the Neo4j's web site),您的问题称为 "Dense node" 或 "Supernode":连接过多的节点。
还是按照书上说的,超级节点
"becomes a real problem for graph traversals because the graph database management system will have to evaluate all of the connected relationships to that node in order to determine what the next step will be in the graph traversal."
Rik 提出的解决方案非常接近您的解决方案(添加一个中间节点):它包括在用户和您喜欢的帖子之间添加一个 "meta" 节点。这个元节点最多应该有一百个连接。如果当前元节点达到 100 个连接,则必须创建一个新的元节点并将其添加到层次结构中,如图所示,以流行艺术家和您的粉丝为例:
Neo4j 团队一直在努力提高超级节点的性能,如 this Github commit(例如)所示,它改变了节点关系在磁盘上的存储方式,以一种链表结构。
我认为最好的办法是一开始就让你的图形模型尽可能简单。您(还)没有密集节点问题,过早的优化可能会给您的模型增加一些不必要的复杂性。如果将来密集节点成为问题,您可以更准确地更改模型。一开始,简单是个不错的选择。
您可以在这些链接中阅读更多关于图形数据库中超级节点的信息:
- Neo4j super node issue - fanning out pattern
- Dealing with supernodes in ArangoDB
- MATCHing Paths with Very Dense Nodes in Neo4j 2.2