说我在管理收藏品。我有成千上万的棒球交易卡,数以千计的游戏卡(想想魔术:聚会),然后成千上万的桌布。
我在关系数据库中潜藏了20多年的部分对数以千计的Neo4J节点漂浮在太空中的想法感到不舒服。
所以我倾向于用一个节点收集它们,例如(:BASEBALL_CARDS),(:MTG_CARDS),当然还有(:DOILIES)。这个想法是这些都是单身。
现在,如果我想要所有可能引用某个球员的棒球牌,我可以做类似的事情:
(:BASEBALL_CARDS)-[GATHERS]->(:BASEBALL_CARD)-[:FEATURES]->(p:PLAYER {name: '...'})
拥有:BASEBALL_CARDS单例是非常令人欣慰的,但它是否能做更多的事情,而不是通过索引来实现:BASEBALL_CARD?
(:BASEBALL_CARD)-[:FEATURES]->(p:PLAYER {name: '...'})
拥有数以千计的自由范围节点是最佳做法吗?
答案 0 :(得分:2)
图数据库的一个特殊优点是本地查询:关系存在于实例中,而不是类型中。特别挑战(除了建模之外)确定本地查询的起点(并保持局部查询,即避免路径爆炸)。在Neo4j 1.x中,您的One Node是一种实现某种查询起点的方法。使用2.x和引入标签,索引:BaseballCard
是实现相同目标的标准方法。如果该One Node的目的是作为示例中查询类型的起点,那么最好使用标签索引。 1.x中的一个常见问题是,具有相同类型和方向的关系数量增加的节点最终成为遍历的瓶颈。人们开始将您的One Node分区为A Paged Handful of Nodes,类似
(:BaseballCards)-[:GATHERS]->(:BaseballCards1to10000)-[:GATHERS]->(:BaseballCard)
查找本地查询起点的目的通常是标签,可能与基本的普通本地遍历相结合,而不是由少数几个节点提供。然后,如果它让你的神经平静或满足你对这个节点的史诗感,那么无论如何都要拥有它。由于查询的位置,它不会对你造成伤害。
但是,在您的示例中,One Node和:BaseballCard
上的索引都不能最好地充当本地查询的起点。最感兴趣的模式是玩家的名字。如果您在(:Player)
上对name
编制索引,那么您将获得最佳起点。跨越一个或少数* [:FEATURES]
关系的遍历非常便宜,并且对:BaseballCard
标签的另一端进行简单测试,您就完成了。你当然可以为所有共享名字的玩家维护一个节点......
在我最谦卑的意见中,几乎不需要感到不适。但是,我确实想要肯定并赞扬你的不安,在这方面:图表对连接数据最有效。收集棒球卡的特定连接似乎并没有增加新的理解或提高性能,但是只要存在断开连接的数据,就有可能发现令人兴奋和有意义的模式。也许在未来,卡片将通过模式连接,这些模式表示其价值范围,层压质量,或之前所有者的链接列表,或者它们作为日期对话启动者的效果。缺乏关系是为了找到一个缺失的链接,为您的数据带来巨大的洞察力和价值。
*少数,假设不止一张棒球卡具有同一个玩家,或者某些棒球运动员也出现在Magic:The Gathering的牌上。我在两个领域都是文盲,所以我想至少考虑到这种可能性。
答案 1 :(得分:2)
具有讽刺意味的是,当图形DB背后的整个想法使节点之间的连接成为第一类DB构造时,你担心节点“在空间中漂浮”。
但我认为你真正关心的是节点不“属于一个表”(用关系数据库的说法)。因此,您可以更自如地创建一个特殊的单例节点,在某种意义上它取代了一个表,您可以从中访问应该属于该表的所有节点。
节点label
可以看作是“表名”的等价物。因此,不仅您不需要创建单个“表节点”,这样做会浪费数据库资源,并使查询复杂化并减慢速度。 neo4j可以快速访问具有相同标签的所有节点。