是否有一组最佳实践来处理如何在图形数据库中建模数据(我现在正在考虑arangodb,但问题是否适用于其他平台)?这是一个实际案例来说明我的问题:
假设我们正在为用户创建一个集中的联系人列表。每个用户都有联系人,但有些联系人可能对用户是共同的约翰认识玛丽,马克知道玛丽。因此我会有3个节点(约翰,玛丽和马克),但约翰应该只看到他与玛丽的关系,而不是马克与玛丽的关系
那么如何设计完整的图表以支持用户访问他们的信息呢?
选项1:为每个用户创建1个图表。这样,我确切地知道谁可以看到什么(例如,我可以使用用户ID为我的所有集合添加前缀)。这很简单,但会复制大量数据(例如,如果我将所有家人都放在数据库中,我的兄弟也会这样做,在不同的图表中创建两次相同的数据)
选项2:使用Contact节点和用户节点创建1个通用图。我将联系John,Mary和Marc联系,但代表John的User节点将仅链接到Contact节点John和Mary。这样我就知道只获得连接到我关注的用户节点的联系节点。 问题是边缘无法链接到用户节点(我不能有从边缘到边缘的边缘......我可以吗?)。因此,我必须向所有边添加user_id属性,以便仅获取与当前用户相关的属性。 这稍微好一些,因为我不需要复制节点,但我仍然需要复制边缘,因为它们是用户特定的
选项3:使用权限表执行SQL,维护联系人ID列表以及用户可以查看哪些节点和哪些边缘(加入时很重)
选项4:???
与所有内容一样,有很多方法可以达到解决方案,但我想知道什么是最佳实践来平衡插入/删除方法的清洁度和性能......知道性能可能取决于平台
答案 0 :(得分:1)
我建议选项4:
首先,我不区分用户和联系节点,但所有节点都应该是联系节点。 如果您创建新用户,则基本上为他创建一个新联系人(或使用现有联系人)并将您的应用程序身份验证连接到此特定联系人。
然后,您可以使用有向边创建用户的联系人列表。 假设您有两个用户John和Mary,而John可以将Mary添加到他的联系人列表中,但Mary无法识别。如果她想添加约翰这意味着你将添加第二个边缘。 如果你想只有对称的联系人(如果John将Mary添加到他的列表中,他应该自动出现在她的列表中),你只需在查询中忽略这个方向。
如果您现在想要获取John的联系人,可以通过选择John的邻居来完成。
在ArangoDB中,可以使用两个集合来实现,例如Contact
和Knows
,其中Knows
保留边缘。
以下代码粘贴到arangosh中会产生上述情况:
db._create("Contact");
db._createEdgeCollection("Knows");
db.Contact.save({_key: "John", mail: "john@example.com"});
db.Contact.save({_key: "Mary", mail: "mary@somewhere.com"});
db.Contact.save({_key: "Marc", mail: "marc@somewhereelse.com"});
db.Knows.save("Contact/John", "Contact/Mary", {});
db.Knows.save("Contact/Marc", "Contact/Mary", {});
查询用户John的联系人列表:
db._query('RETURN NEIGHBORS(Contact, Knows, "John", "outbound")').toArray()
应该给玛丽作为结果,没有关于马克的信息。
如果您不想按照我的建议加入联系人和用户帐户,您也可以将它们分隔在不同的集合中,在这种情况下,您必须稍微修改边缘和查询:
db.Knows.save("User/John", "Contact/Mary", {});
db.Knows.save("User/Marc", "Contact/Mary", {});
db._query('RETURN NEIGHBORS(Users, Knows, "John", "outbound")').toArray()
应该给出相同的结果。
编辑: 关于您在选项2中的问题: 在ArangoDB中,实际上可以将边缘指向其他边缘,但是在图形功能中构建现在将认为边缘指向它们是节点。这意味着他们不会自动遵循他们的指示。但是您可以在进一步的AQL语句中使用这些结果边缘,并继续使用AQL功能进行搜索。