快捷搜索:  汽车  科技

数据建模用什么主键(图数据建模键)

数据建模用什么主键(图数据建模键)MATCH (:A { scode: "Y" })-[:LINKED_TO]->(r:Record { ccode: "X" })关键是,在大多数情况下,良好的数据模型可以消除对复合键的需要。MATCH (r:Record { ccode: "X" scode: "Y" })通常会比这更糟糕:智能键通常是将信息编码为键的复合值。想象一下,我们有一个订购系统,我们确定了客户订单为2020-06-19-VA-9912。它似乎可以方便地编码订单日期(2020-06-19),订单状态(弗吉尼亚)和订单号(9912)中的单个键。在实践中,有几个原因,智能键通常最终会发生灾难:关于智能键的关键要点是它们总是具有低不透明度;这就是他们的重点。在关系数据库中,它是典型的,以定义两个或多个属性的复合键,但在我的视图中,从未在图表中有意义

在两个以前的文章中,我们涵盖了图形数据建模的方面,例如类别变量,以及关系如何工作。在本文中,让我们解决如何用键(Key)识别图表中的东西。

数据建模用什么主键(图数据建模键)(1)

什么是键?

图形键是属性或一组属性,可帮助识别图形中的节点或关系。

它们经常用作图形遍历的起点,或者用作约束的条件。

我们想要什么键?

在我们在Neo4J中的键进入不同选项之前,让我们列出对一个非常好的数据库密钥的属性。

  • 所有者:我们必须知道谁负责键。有人必须发出它,有人不得不说那是哪个。这可能是数据库本身,可能是应用程序开发人员,或者可能是某些外部权限(例如,如果您使用驱动程序的许可证号作为密钥,则为您的本地DMV)。
  • 稳定性:数据在我们周围不断变化。我们希望稳定的标识符,使旧系统和代码可以参考较新的数据。
  • 唯一性上下文:当然键必须是独一无二的,但它们在某种情况下是独一无二的。驾驶执照ID仅在美国的某个州范围内是独一无二的(它可以在其他地方重用)。
  • 透明度:这意味着,键是内部含义吗?一个人可以通过查看前一个人来猜出下一个键吗?如果您看到了像“2020-06-19-ABC”这样的键,那么您可能会推断键值是具有后缀的日期,这不会是不透明的。
这样做
  • 有一个权限,您可以为您或您可以与之生活的第三方,发布有关如何做出有意义的事情的规则。无论权威是什么,无论是你还是第三方,知道它是谁。
  • 使用单个属性,并对其进行唯一的属性约束,这将确保您的密钥无法复制并添加快速查找的索引。
  • 具有尽可能宽的唯一环境,以防止您重复失败。
  • 使用不透明标识符。这足以让键是独一无二的,不要试图用额外的意义定义它。
不要这样做不要使用智能键

智能键通常是将信息编码为键的复合值。想象一下,我们有一个订购系统,我们确定了客户订单为2020-06-19-VA-9912。它似乎可以方便地编码订单日期(2020-06-19),订单状态(弗吉尼亚)和订单号(9912)中的单个键。在实践中,有几个原因,智能键通常最终会发生灾难:

  • 如果订单的日期输入不正确,则记录的ID需要更改(?!?!)。
  • 它鼓励其他开发人员试图“解析ID”以提取信息,这是一种痛苦,并且可以给出错误的结果(如果订单号更改!)。

关于智能键的关键要点是它们总是具有低不透明度;这就是他们的重点。

不要在图中使用复合键

在关系数据库中,它是典型的,以定义两个或多个属性的复合键,但在我的视图中,从未在图表中有意义。通常有人使用复合键的通常原因是因为列之间的依赖关系。例如,也许您的客户代码 状态代码一起是唯一标识记录的原因。但由于图允许您拥有您想要的节点,因此这个Cypher代码:

MATCH (r:Record { ccode: "X" scode: "Y" })

通常会比这更糟糕:

MATCH (:A { scode: "Y" })-[:LINKED_TO]->(r:Record { ccode: "X" })

关键是,在大多数情况下,良好的数据模型可以消除对复合键的需要。

在Neo4j中的选择是什么?neo4j内部ID

每个节点和关系都会获得自己的“内部”标识符,您可以访问id()函数。

数据建模用什么主键(图数据建模键)(2)

> internal ID of a node

这些ID的优势在于它们总是保证为您服务。通过ID查找在Neo4J中非常快,因为内存工作中的图形存储方式。但是,由于多种原因,内部节点ID(在我的视图中)为非常糟糕的应用程序标识符提供:

  • 他们被重用了。它们保证在图形中是唯一的,但如果删除节点25并继续创建数据,则稍后可能有不同的节点25。
  • 它们不在数据库之间跟踪。如果将所有数据从系统A转储并将其加载到其他系统B中,则不一定具有相同的ID。因此,它们对于在不同的数据库中连接数据,例如使用Neo4j Fabric。

基本上,你得到的唯一保证是它们在全球范围内(对该图,而不是DBMS)唯一。虽然这是不透明的,但标识符的权限是数据库(不是您的应用程序),唯一性上下文仅在单个系统上被选中到单个图形。

全球独特的ID

使用Apoc内置的UUIDS,您可以像这样创建它们:

CREATE (m:Thing { id: apoc.create.uuid() });

数据建模用什么主键(图数据建模键)(3)

> An APOC-generated UUID

这些是非常好的,因为你是权威,并自己管理他们。它们是稳定的,永远不需要改变。它们在所有环境中都非常独特,它们非常不透明。它们是128位数字,其是伪随机生成的。实际上,你不必担心碰撞,因为空间太大,如果你这样生成103万亿的标识符(我们很确定你将在那之下)碰撞的机会仍然是十亿分之一。够好了。

他们又带来了缺点。

  • 它们是大而笨重的,并且包含比标识符所需的更多数据,这意味着当您有数十亿个时,它们会占用空间。
  • 他们对人类可读性保持敌对,如果您的ID在URL中最终有任何内容,这可能很重要,这很常见。
别人的身份证

让我们面对它,通常我们的来源数据来自其他地方。如果我们从Twitter导入Tweets到图形中,那么所有推文都有现有ID。经常经常,良好的方法将是通过您的数据导入附带的其他人ID方案。

这很难说这种方法是什么,因为它取决于标识符是什么。我们能做得最好的就是回到那些我们正在寻找的原则(不透明度,独特性等),并评估一个身份证。

我们可以谈谈采用别人的标识符的具体否定:

  • 权威:你不是。这意味着您可以信任您数据的某些元素对此外部权威的ID。这是一个问题吗?取决于你的情况。也许,也许不是。
  • 混合能力:您的图表现在可能有一个馈线源(例如,Twitter)。当您开始导入其他来源时会发生什么?如果您带入Facebook帖子,您是否有两个标识符,或者ID依赖于源代码吗?这很快就会得到丑陋。

作为一般性推荐 - 始终存储您可以掌握的任何上游标识符。但不要用它来成为你的标识符。使用它与上游系统相关联。除了存储远程标识符之外,选择自己的ID没有错。

自动递增数字

一种常见的方法是使用自动递增号。Neo4j不支持这种情况,但在其他库中找到它很常见,并且它在关系世界中是一种常见的技术。这通常不是最好的方法,因为:

  • 如果每个节点标签获得是自己的“递增器”,则ID对图形并不是真正的唯一标签。这使您的密钥隐式ID 标签,而不仅仅是ID。这是你可以选择的最弱“唯一性的范围”。
  • 它具有与Neo4J内部ID相同的潜在重用弱点。

据说,这种方法仍然是由您(好的)控制得不透明(好),以及紧凑型/储存效率。

关系标识符

as neo4j 4.1.0,数据库没有常规的B树关系属性索引(它确实支持关系属性上的全文索引)这具有重要的后果,并意味着不可能快速查找个体关系一个ID,因为数据库根本无法将其存储在内。找到关系的方式是通过查找一个(或两者)的事件节点,如下所示:

MATCH (a:Person { id: 1 })-[r:KNOWS]->(b:Person { id: 2 }) RETURN r;

在这种情况下,有效地使用“从”和“到”节点作为关系密钥。id()函数仍然存在关系,它们都有内部Neo4j ID,但通常我们不需要将属性ID分配给关系。它们不仅可以在这种方式定位,但缺乏财产索引,按键查明不会是无论如何的有效方法。

本文是一系列的一部分;如果您发现它有用,请考虑在标签,关系,超节点和分类变量上读取其他人。

(本文由闻数起舞翻译自David Allen的文章《Graph Data Modeling: All About Keys》,转载请注明出处,原文链接:https://medium.com/neo4j/graph-data-modeling-keys-a5a5334a1297)

猜您喜欢: